2014-10-24 3 views
0

단순히 쉘 스크립트에 변수를 전달하려하지만 전달되지 않습니다. 나는 의 파이썬 문서의 예제를 따르지만 작동하지 않습니다. 내가 뭘 놓치고 있니?내 변수가 내 서브 프로세스에 포함되지 않는 이유는 무엇입니까?

subprocess.Popen(['./script.sh' + variable] , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
+0

문자열을 사용하지 않고 목록을 사용하고 있습니까? – Totem

+0

@Totem, 둘 다 작동합니다. 'shell = True'를 사용하면 목록의 첫 번째 요소가 실행할 스크립트로 셸에 전달되고 다른 모든 요소는 추가 인수로 셸에 전달됩니다. –

답변

1

추가 공간 ./script.sh 후 :

subprocess.Popen(['./script.sh ' + variable] , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
+0

그래, 내 머리 속에 잘못 해석 했어. 이 경우 (한 문자열 인수 목록)를 실제 실수 (두 개의 문자열 인수가있는 목록)와 혼동했습니다. – chepner

+0

고마워! 간단하게 공간을 추가했습니다. – nonlinearmind

+0

@nonlinearmind, ... "일한"주변의주의 사항을 기억하십시오. 변수에 공백이없고 glob 문자가없고 쉘 구문이없는 경우 작동합니다 ... –

0

단지 스크립트 이름 뒤에 공백 추가합니다 :

subprocess.Popen(['./script.sh ' + variable], shell=True, 
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
2

당신은 여기 shell=True를 사용하지 않아야을 변수의 실제 셸 구문 (예 : >file.log)을 실행하지 않는 한 모두. 당신이 정말shell=True를 원하는 경우


subprocess.Popen(['./script.sh', variable], 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

, 당신은 너무 안전하게 할 수있는 몇 가지 옵션이 있습니다. 첫번째 셸 탈출을 방지하기 위해 (파이썬 3 shlex.quote() 또는) pipes.quote()를 사용하는 것이다

subprocess.Popen('./script.sh ' + pipes.quote(variable), shell=True, 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

번째 (후속 인자로 이름을 전달 생성에 $0된다 빈 문자열을주의한다 쉘) :

subprocess.Popen(['./script.sh "$1"', '', variable], shell=True, 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

가 기억 Bobby Tables는 SQL위한 것이 아닙니다 - 그의 여동생 Susan $(rm -rf /)도 거기에있다.

+1

그리고 Susan이 Popen을 사랑하는만큼'eval'을 좋아하는 사촌 인'Barry ', __import __ (os) .system ("rm -rf /")'을 잊지 마세요. : – abarnert

1

두 가지 방법으로 작업을 수행 할 수 있습니다. 그리고, 그 위에, 당신은 잘못하고 있지만, 단지 "잘못하고있는 것"을 고치는 것은 답이 아닙니다.

두 개의 인수를 목록에 넣은 다음 ['./script.sh', variable]과 같이 셸없이 시작할 수 있습니다. 보통 더 좋습니다. 셸을 사용한다는 것은 인용 및 우발적 또는 악의적 인 주입으로 처리해야하며 입력 및 출력을 방해하고 성능 비용을 추가한다는 것을 의미합니다. 그래서, 당신이 그것을 필요하지 않으면, 그것을 사용하지 마십시오.

또는 두 개의 인수를 문자열에 넣은 다음 './script.sh ' + variable과 같은 셸을 사용하여 시작할 수 있습니다.

그러나 두 개의 인수를 문자열에 넣을 수는 없으며 해당 문자열을 목록에 넣을 수 없습니다. 어떤 경우에는 일하게 될 것이지만, 그것은 당신이 의지 할 수있는 것이 아닙니다.

경우에 따라 셸이없는 * 또는 셸이없는 문자열 **을 사용할 수 있지만 일반적으로 수행중인 작업을 모르는 경우에는 수행하지 않아야합니다. . 당신이 필요 특정 이유가없는 한 여전히 하나의 문자열의 목록을 사용하지 않아야 ***


는 인수 목록을 사용하려면 다음을 수행

subprocess.Popen(['./script.sh', variable], shell=False, …) 

이 문자열은 합쳐진 문자열 목록이 아닌 두 문자열 목록이며 그 문자열은 shell=False입니다.


이 같은 인수 사이의 공간을 생략하고, 비 정적 인수를 인용하지 마십시오 목록에서 명령 줄을 넣지 마십시오, 쉘 명령 줄을 사용하려면 :

Windows에서 쉘 목록을 사용하여

*

subprocess.Popen('./script.sh ' + shlex.quote(variable), shell=True, …) 

는 결코 유용하다; 그들은 단지 불특정 된 방식으로 결합됩니다. 그러나 유닉스에서 subprocess은 효과적으로 '/bin/sh''-c'을 목록 앞에 추가하고 /bin/sh의 arg 목록으로 사용합니다.이 인수는 쉘 인수를 인용하는 것보다 간단 할 수 있으며 적어도 shell=False으로 명시 적으로 /bin/sh을 호출하는 것보다 논증 할 수있을만큼 간결합니다.

** Unix에서 쉘없이 문자열을 사용하면 유용하지 않습니다. 단지 이름이 전체 문자열 인 프로그램을 찾으려고 시도하는데, 실패 할 것입니다 (정말로 운이 좋으면 제외). 그러나 Windows에서는 유용 할 수 있습니다. subprocess은 인수를 CreateProcess에 전달할 문자열로 결합하려고 시도합니다. 그러면 MSVCRT가 다른 인수의 동일한 인수 목록으로 다시 구문 분석하고 어떤 경우에는 해당 문자열을 직접 작성해야합니다.

*** 기본적으로 ['/bin/sh', '-c', <command line>]을 정확히 생성하고 싶습니다.

+0

'subprocess.Popen (arg_list, shell = True)'는'subprocess.Popen ([ 'sh', '-c'] + arg_list, shell = False)'와 동일하다. . 따라서 첫 번째 인수 _is_는 항상 스크립트를 실행하는 데 사용되며 이후 인수는 문자열로 결합되지 않습니다. –

+0

... 첫 번째 목록 요소로 전달 된 스크립트 내부에서 인수 벡터 (' "$ 1"',' "$ 2"'등)를 참조하여 의도적으로 이점을 취할 수 있습니다. –

+0

@CharlesDuffy : 좋아, 각주를 더 정확하게 작성했습니다. 보다 나은? – abarnert

관련 문제