使用os.system()在Python中执行'source HOME/.bashrc
我正在写一个Python脚本(在Linux上),这个脚本是用来添加一些shell别名的(把它们写入HOME/.bash_aliases
文件)。
为了让别名在写入后立即可用,我需要执行以下bash内置命令:
source HOME/.bashrc
source
是一个bash内置命令,所以我不能直接这样做:
os.system(source HOME/.bashrc)
如果我尝试类似这样的操作:
os.system('/bin/bash -c source HOME/.bashrc')
...脚本会卡住(就像在等待什么一样)。
有什么建议吗?
4 个回答
这是来自于“我可以用别名从Python脚本执行程序吗?”的一个有效解决方案:
import subprocess
sp = subprocess.Popen(["/bin/bash", "-i", "-c", "nuke -x scriptpath"])
sp.communicate()
你想做的事情是不可能的。或者说,你的做法是不对的。
你的bash命令写错了。
bash -s command
并不会执行command
,它只是把字符串“command”存到变量$1
里,然后让你回到命令提示符。这就是为什么你的python脚本看起来像是卡住了。你应该用bash -c command
。你为什么要加载
.bashrc
? 直接加载.bash_aliases
不就够了吗?即使你把bash命令写对了,改动也只会在从python启动的bash会话中生效。一旦这个bash会话关闭,你的python脚本结束,你就回到了原来的bash会话。所有在从python启动的bash会话中的改动都会丢失。
每次你想在当前的bash会话中做改动,都必须在这个会话里进行。你从bash运行的大多数命令(系统命令、python脚本,甚至bash脚本)都会启动一个新的进程,而你在那个新进程中做的任何事情都不会影响到你最初的bash会话。
source
是一个bash内置命令,它允许你在当前运行的bash会话中执行命令,而不是启动另一个进程来执行命令。定义一个bash函数也是在当前运行的bash会话中执行命令的另一种方式。
想了解更多关于加载和执行的内容,可以查看这个回答。
你可以怎么做来实现你的目标
修改你的python脚本,只做必要的.bash_aliases
改动。
准备一个bash脚本来运行你的python脚本,然后加载.bash_aliases
。
#i am a bash script, but you have to source me, do not execute me.
modify_bash_aliases.py "$@"
source ~/.bash_aliases
在你的.bashrc
中添加一个别名来加载那个脚本。
alias add_alias='source modify_bash_aliases.sh'
现在当你在bash提示符中输入add_alias some_alias
时,它会被替换为source modify_bash_aliases.sh
并执行。因为source
是一个bash内置命令,脚本中的命令会在当前运行的bash会话中执行。虽然python脚本仍然会在另一个进程中运行,但后续的source
命令会在你当前的bash会话中执行。
另一种方法
修改你的python脚本,只做必要的.bash_aliases
改动。
准备一个bash函数来运行你的python脚本,然后加载.bash_aliases
。
add_alias() {
modify_bash_aliases.py "$@"
source ~/.bash_aliases
}
现在你可以这样调用这个函数:add_alias some_alias
你想要的事情是做不到的。一个程序(也就是你的脚本)不能改变它被调用的环境(也就是你运行它的那个命令行)。
不过,有一种方法可以让你做到类似的事情,那就是把它写成一个bash函数。这样这个函数会在同一个进程中运行,就可以修改调用它的环境。不过要注意,在运行时引入其他配置可能会有一些不好的副作用,这取决于用户在他们的bashrc文件里设置了什么。