단순히 쉘 스크립트에 변수를 전달하려하지만 전달되지 않습니다. 나는 의 파이썬 문서의 예제를 따르지만 작동하지 않습니다. 내가 뭘 놓치고 있니?내 변수가 내 서브 프로세스에 포함되지 않는 이유는 무엇입니까?
subprocess.Popen(['./script.sh' + variable] , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
단순히 쉘 스크립트에 변수를 전달하려하지만 전달되지 않습니다. 나는 의 파이썬 문서의 예제를 따르지만 작동하지 않습니다. 내가 뭘 놓치고 있니?내 변수가 내 서브 프로세스에 포함되지 않는 이유는 무엇입니까?
subprocess.Popen(['./script.sh' + variable] , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
추가 공간 ./script.sh 후 :
subprocess.Popen(['./script.sh ' + variable] , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
그래, 내 머리 속에 잘못 해석 했어. 이 경우 (한 문자열 인수 목록)를 실제 실수 (두 개의 문자열 인수가있는 목록)와 혼동했습니다. – chepner
고마워! 간단하게 공간을 추가했습니다. – nonlinearmind
@nonlinearmind, ... "일한"주변의주의 사항을 기억하십시오. 변수에 공백이없고 glob 문자가없고 쉘 구문이없는 경우 작동합니다 ... –
단지 스크립트 이름 뒤에 공백 추가합니다 :
subprocess.Popen(['./script.sh ' + variable], shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
당신은 여기 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 /)
도 거기에있다.
그리고 Susan이 Popen을 사랑하는만큼'eval'을 좋아하는 사촌 인'Barry ', __import __ (os) .system ("rm -rf /")'을 잊지 마세요. : – abarnert
두 가지 방법으로 작업을 수행 할 수 있습니다. 그리고, 그 위에, 당신은 잘못하고 있지만, 단지 "잘못하고있는 것"을 고치는 것은 답이 아닙니다.
두 개의 인수를 목록에 넣은 다음 ['./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>]
을 정확히 생성하고 싶습니다.
'subprocess.Popen (arg_list, shell = True)'는'subprocess.Popen ([ 'sh', '-c'] + arg_list, shell = False)'와 동일하다. . 따라서 첫 번째 인수 _is_는 항상 스크립트를 실행하는 데 사용되며 이후 인수는 문자열로 결합되지 않습니다. –
... 첫 번째 목록 요소로 전달 된 스크립트 내부에서 인수 벡터 (' "$ 1"',' "$ 2"'등)를 참조하여 의도적으로 이점을 취할 수 있습니다. –
@CharlesDuffy : 좋아, 각주를 더 정확하게 작성했습니다. 보다 나은? – abarnert
문자열을 사용하지 않고 목록을 사용하고 있습니까? – Totem
@Totem, 둘 다 작동합니다. 'shell = True'를 사용하면 목록의 첫 번째 요소가 실행할 스크립트로 셸에 전달되고 다른 모든 요소는 추가 인수로 셸에 전달됩니다. –