Significado real de 'shell=True' en el subproceso
Estoy llamando a diferentes procesos con el subprocess
módulo. Sin embargo, tengo una pregunta.
En el siguiente código:
callProcess = subprocess.Popen(['ls', '-l'], shell=True)
y
callProcess = subprocess.Popen(['ls', '-l']) # without shell
Ambos trabajan. Después de leer los documentos, descubrí que eso shell=True
significa ejecutar el código a través del Shell. Eso significa que, en ausencia, el proceso se inicia directamente.
Entonces, ¿qué debería preferir para mi caso? Necesito ejecutar un proceso y obtener su resultado. ¿Qué beneficio tengo al llamarlo desde dentro o fuera del caparazón?
El beneficio de no llamar a través del shell es que no estás invocando un "programa misterioso". En POSIX, la variable de entorno SHELL
controla qué binario se invoca como "shell". En Windows, no hay ningún descendiente del shell Bourne, sólo cmd.exe.
Entonces, al invocar el shell se invoca un programa elegido por el usuario y depende de la plataforma. En términos generales, evite las invocaciones a través del shell.
La invocación a través del shell le permite expandir las variables de entorno y los archivos globales de acuerdo con el mecanismo habitual del shell. En los sistemas POSIX, el shell expande los archivos globales a una lista de archivos. En Windows, un archivo global (por ejemplo, "*.*") no se expande mediante el shell (pero las variables de entorno en una línea de comando se expanden mediante cmd.exe).
Si cree que desea expansiones de variables de entorno y globs de archivos, investigue los ILS
ataques de 1992 a servicios de red que realizaban invocaciones de subprogramas a través del shell. Los ejemplos incluyen las diversas sendmail
puertas traseras que involucran ILS
.
En resumen, utilice shell=False
.
>>> import subprocess
>>> subprocess.call('echo $HOME')
Traceback (most recent call last):
...
OSError: [Errno 2] No such file or directory
>>>
>>> subprocess.call('echo $HOME', shell=True)
/user/khong
0
Establecer el argumento del shell en un valor verdadero hace que el subproceso genere un proceso de shell intermedio y le indique que ejecute el comando. En otras palabras, usar un shell intermedio significa que las variables, los patrones globales y otras características especiales del shell en la cadena de comando se procesan antes de ejecutar el comando. Aquí, en el ejemplo, $HOME se procesó antes del comando echo. En realidad, este es el caso del comando con expansión de shell, mientras que el comando ls -l se considera un comando simple.
fuente: Módulo de subproceso
Aquí se muestra un ejemplo en el que las cosas podrían salir mal con Shell=True
>>> from subprocess import call
>>> filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / # THIS WILL DELETE EVERYTHING IN ROOT PARTITION!!!
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
Consulte el documento aquí: subprocess.call()
Ejecutar programas a través del shell significa que toda la entrada del usuario pasada al programa se interpreta de acuerdo con la sintaxis y las reglas semánticas del shell invocado. En el mejor de los casos, esto sólo causa molestias al usuario, porque éste debe obedecer estas reglas. Por ejemplo, las rutas que contienen caracteres especiales del shell, como comillas o espacios en blanco, deben tener caracteres de escape. En el peor de los casos, provoca fugas de seguridad, porque el usuario puede ejecutar programas arbitrarios.
shell=True
A veces es conveniente hacer uso de funciones específicas del shell, como la división de palabras o la expansión de parámetros. Sin embargo, si se requiere dicha característica, utilice otros módulos que se le proporcionan (por ejemplo, os.path.expandvars()
para ampliar parámetros o shlex
dividir palabras). Esto significa más trabajo, pero evita otros problemas.
En resumen: evitarlo shell=True
por todos los medios.