os.system() 호출을 탈출하는 방법은 무엇입니까?
문제
os.system()을 사용할 때 명령에 매개변수로 전달된 파일 이름과 기타 인수를 이스케이프해야 하는 경우가 많습니다.어떻게 해야 하나요?여러 운영 체제/셸에서 작동하지만 특히 bash에서 작동하는 것이 바람직합니다.
현재 다음 작업을 수행 중이지만 이를 위한 라이브러리 함수가 있거나 최소한 더 우아하고/견고하고/효율적인 옵션이 있어야 한다고 확신합니다.
def sh_escape(s):
return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")
os.system("cat %s | grep something | sort > %s"
% (sh_escape(in_filename),
sh_escape(out_filename)))
편집하다: 나는 따옴표를 사용하는 간단한 대답을 받아들였습니다. 왜 그렇게 생각하지 않았는지 모르겠습니다.나는 '와'가 조금 다르게 동작하는 Windows에서 왔기 때문에 추측합니다.
보안과 관련하여 우려 사항을 이해하지만 이 경우 os.system()이 제공하는 빠르고 쉬운 솔루션에 관심이 있으며 문자열의 소스는 사용자가 생성하지 않았거나 적어도 사용자가 입력한 것입니다. 신뢰할 수 있는 사용자(나).
해결책
이것이 내가 사용하는 것입니다:
def shellquote(s):
return "'" + s.replace("'", "'\\''") + "'"
쉘은 항상 인용된 파일 이름을 허용하고 문제의 프로그램에 전달하기 전에 주변 인용문을 제거합니다.특히 이는 공백이나 기타 불쾌한 셸 메타 문자가 포함된 파일 이름과 관련된 문제를 방지합니다.
업데이트:Python 3.3 이상을 사용하는 경우 다음을 사용하십시오. shlex.quote 스스로 굴리는 대신.
다른 팁
shlex.quote()
Python 3부터 원하는 것을 수행합니다.
(사용 pipes.quote
Python 2와 Python 3을 모두 지원하려면)
아마도 당신은 이 제품을 사용하는 특별한 이유가 있을 것입니다. os.system()
.하지만 그렇지 않다면 아마도 다음을 사용해야 할 것입니다. subprocess
기준 치수.파이프를 직접 지정하고 셸 사용을 피할 수 있습니다.
다음은 PEP324:
Replacing shell pipe line ------------------------- output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0]
아마도 subprocess.list2cmdline
더 좋은 샷인가요?
Pipes.quote는 실제로 Python 2.5 및 Python 3.1에서 손상되었으며 사용하기에 안전하지 않습니다. 길이가 0인 인수를 처리하지 않습니다.
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
보다 Python 문제 7476;Python 2.6 및 3.2 이상에서 수정되었습니다.
나는 os.system이 사용자를 위해 구성된 명령 셸을 호출한다고 믿기 때문에 플랫폼 독립적인 방식으로는 이를 수행할 수 없다고 생각합니다.내 명령 셸은 bash, emacs, ruby 또는 quake3 등 무엇이든 될 수 있습니다.이러한 프로그램 중 일부는 사용자가 전달하는 인수의 종류를 기대하지 않으며, 설령 그랬더라도 동일한 방식으로 탈출한다는 보장은 없습니다.
알아채다:이것은 Python 2.7.x에 대한 답변입니다.
에 따르면 원천, pipes.quote()
"라는 방법이다.문자열을 단일 인수로 안정적으로 인용합니다. /bin/sh".(그렇긴 하지만 버전 2.7부터 더 이상 사용되지 않음 마침내 Python 3.3에서 공개적으로 공개되었습니다. shlex.quote()
기능.)
~에 다른 한편으로는, subprocess.list2cmdline()
"라는 방법이다.동일한 규칙을 사용하여 일련의 인수를 명령줄 문자열로 변환합니다. MS C 런타임".
여기에는 명령줄에 대한 문자열을 인용하는 플랫폼 독립적인 방법이 있습니다.
import sys
mswindows = (sys.platform == "win32")
if mswindows:
from subprocess import list2cmdline
quote_args = list2cmdline
else:
# POSIX
from pipes import quote
def quote_args(seq):
return ' '.join(quote(arg) for arg in seq)
용법:
# Quote a single argument
print quote_args(['my argument'])
# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)
내가 사용하는 기능은 다음과 같습니다.
def quote_argument(argument):
return '"%s"' % (
argument
.replace('\\', '\\\\')
.replace('"', '\\"')
.replace('$', '\\$')
.replace('`', '\\`')
)
그건:나는 항상 인수를 큰따옴표로 묶은 다음 큰따옴표 안의 특수 문자만 백슬래시로 묶습니다.
시스템 명령을 사용한다면 os.system() 호출에 포함되는 내용을 화이트리스트에 추가해 보겠습니다.예를 들어..
clean_user_input re.sub("[^a-zA-Z]", "", user_input)
os.system("ls %s" % (clean_user_input))
subprocess 모듈이 더 나은 옵션이므로 가능하면 os.system/subprocess와 같은 모듈은 사용하지 않는 것이 좋습니다.
실제 대답은 다음과 같습니다.사용하지 마세요 os.system()
우선.사용 subprocess.call
대신 이스케이프되지 않은 인수를 제공하십시오.