I have the following python function that allows me to run shell commands from within a python script:
import subprocess
def run_shell_command(cmd,cwd=None):
retVal = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, cwd=cwd);
retVal = retVal.stdout.read().strip('\n');
return(retVal);
This allows me to do things like:
output = run_shell_command("echo 'Hello world'")
My question is: with the definition of run_shell_command
above, which type of shell is started? (e.g. login vs interactive).
Knowing which shell is started would help know which which dot
files (e.g. .bashrc
, .profile
, etc.) are executed prior to my shell command.
It's /bin/sh
on POSIX. See the source code subprocess.py
(quoting Python 2.7 here):
def _execute_child(self, args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines,
startupinfo, creationflags, shell, to_close,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite):
"""Execute program (POSIX version)"""
if isinstance(args, types.StringTypes):
args = [args]
else:
args = list(args)
if shell:
args = ["/bin/sh", "-c"] + args
if executable:
args[0] = executable
[...]
This is mentioned in the Python subprocess
documentation:
The executable argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the args argument. If shell=True, the executable argument specifies which shell to use. On Unix, the default shell is
/bin/sh
. On Windows, the default shell is specified by theCOMSPEC
environment variable. The only reason you would need to specifyshell=True
on Windows is where the command you wish to execute is actually built in to the shell, eg dir, copy. You don’t need shell=True to run a batch file, nor to run a console-based executable.
/bin/sh
on Linux/MacOSX is typically an alias for bash (or bash-compatible - newer versions of Debian use dash), whereas on Unixes like Solaris, it might be classic Bourne Shell.
For Windows, it's usually cmd
or command.bat
.
popen
?I just realized that I haven't answered your 2nd question - but setting shell=True
will spawn a non-login shell (look @AndiDog's source code link, the way the shell is getting forked would create a non-login shell).
Also be aware that using shell=True
, while it allows you to use shell primitives and shortcuts, can also be a security risk, so be sure to check any possible inputs you might use for process spawning.
Warning Executing shell commands that incorporate unsanitized input from an untrusted source makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. For this reason, the use of shell=True is strongly discouraged in cases where the command string is constructed from external input:
>>>
>>> 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 / #
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
shell=False
disables all shell based features, but does not suffer from this vulnerability; see the Note in the Popen constructor documentation for helpful hints in getting shell=False to work.
It's not a login shell, so you don't get .login etc.
If for any reason you need to initialize a shell that thinks it's a login shell, you'll need to execute the shell yourself and (I believe this is still how this is done) change the first character of the argv[0] it sees to be a "-".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With