使用os.system()在Python中执行'source HOME/.bashrc

13 投票
4 回答
27833 浏览
提问于 2025-04-16 03:49

我正在写一个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 个回答

0

这是来自于“我可以用别名从Python脚本执行程序吗?”的一个有效解决方案:

import subprocess
sp = subprocess.Popen(["/bin/bash", "-i", "-c", "nuke -x scriptpath"])
sp.communicate()
3

你想做的事情是不可能的。或者说,你的做法是不对的。

  1. 你的bash命令写错了。bash -s command并不会执行command,它只是把字符串“command”存到变量$1里,然后让你回到命令提示符。这就是为什么你的python脚本看起来像是卡住了。你应该用bash -c command

  2. 你为什么要加载.bashrc? 直接加载.bash_aliases不就够了吗?

  3. 即使你把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

7

你想要的事情是做不到的。一个程序(也就是你的脚本)不能改变它被调用的环境(也就是你运行它的那个命令行)。

不过,有一种方法可以让你做到类似的事情,那就是把它写成一个bash函数。这样这个函数会在同一个进程中运行,就可以修改调用它的环境。不过要注意,在运行时引入其他配置可能会有一些不好的副作用,这取决于用户在他们的bashrc文件里设置了什么。

撰写回答