我想从 python 调用 .bashrc 文件中的别名命令集。然而,由于某种原因,
source ~/.bashrc; command -v command
的返回码是1而不是0,如果直接在shell中执行相同的命令,就会出现这种情况。应该注意的是,使用像 echo
这样的默认命令而不是别名命令,python correclty 返回 0 作为返回码。
为了演示这个问题,我创建了一个最小的示例,其中使用常规 shell 脚本 define_alias.sh 而不是 .bashrc 文件:
test_bash_command.py:
import os
import subprocess
path_home = os.path.expanduser('~')
proc = subprocess.Popen(['/bin/bash', '-c', 'source %s/define_alias.sh; command -v testcommand' % path_home], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_stdout, proc_stderr = proc.communicate()
proc_returncode = proc.returncode
print("Returncode: %s" % proc_returncode)
print("Stdout: %s" % proc_stdout)
print("Stderr: %s" % proc_stderr)
define_alias.sh:
# .bashrc
# imagine this is a .bashrc file
echo "I'm in the shell script"
alias testcommand='echo THIS IS A TEST'
输出:
wssadmin /global/wss/fs01/fk_bpr/waif_v8
$ python test_bash_command.py
Returncode: 1
Stdout: b"I'm in the shell script\n"
Stderr: b''
wssadmin /global/wss/fs01/fk_bpr/waif_v8
$ env -i bash --norc --noprofile
bash-4.4$ bash -c "source /home/wssadmin/define_alias.sh; command -v testcommand; echo $?"
I'm in the shell script
0
bash-4.4$ source /home/wssadmin/define_alias.sh; command -v testcommand; echo $?
I'm in the shell script
alias testcommand='echo THIS IS A TEST'
0
bash-4.4$ exit
exit
wssadmin /global/wss/fs01/fk_bpr/waif_v8
$ source /home/wssadmin/define_alias.sh; command -v testcommand; echo $?
I'm in the shell script
alias testcommand='echo THIS IS A TEST'
0
问题:为什么 python 的返回码不是像 bash 中那样为 0?如何获得给定命令的返回码 0 并另外检索
command -v testcommand
的 stdout 和 stderr (而不是仅具有 echo
命令的 stdout 和 stderr)?
source
命令本身被执行,这可以在打印的stdout
变量中看到。请注意,我不想更改 /bin/bash -c
或 shell=False
中的 subprocess.Popen
参数,否则我会遇到由围绕 run_bash_cmd
的 subprocess.Popen
函数在其他 python 脚本中调用的其他命令的问题.
非常感谢您的帮助!
您需要运行
shopt -s expand_aliases
来启用别名支持,该支持在非交互式 shell 中默认关闭。 (从历史上看,别名是 POSIX sh 标准的用户可移植性实用程序附件中可选交互式扩展的一部分;直到 POSIX 标准的第 7 版修订版,它们才成为正确的基本功能集的一部分)。
>>> subprocess.run(['bash', '-c', 'alias foo=true;'
... 'command -v foo']).returncode
1
>>> subprocess.run(['bash', '-c', 'alias foo=true;'
... 'shopt -s expand_aliases; command -v foo']).returncode
alias foo='true'
0