如果我有一个用bash
以外的语言编写的程序(比如python
),我怎样才能更改环境变量或其中的当前工作目录,使其反映在调用shell中?
我想用它来编写一个简化常见操作的'命令行帮助器'。例如,聪明的cd
。当我在提示符中输入目录名称时,它应该cd
进入它。
[~/]$ Downloads
[~/Downloads]$
甚至
[~/]$ project5
[~/projects/project5]$
然后我找到How to change current working directory inside command_not_found_handle(这正是我想要做的事情之一),它将我介绍给shopt -s autocd
。但是,这仍然无法处理提供的目录不在./
。
另外,如果我想做一些事情,比如从python脚本设置http_proxy
变量,甚至更新PATH
变量,我的选择是什么?
P上。 S.我知道可能没有一种明显的方法可以在python脚本中编写一个魔法命令来自动更新调用shell中的环境变量。我正在寻找一个有效的解决方案,不一定是优雅的。
答案 0 :(得分:1)
这只能通过父shell的参与和帮助来完成。对于执行此操作的程序的实际示例,您可以查看应该如何使用ssh-agent
:
eval "$(ssh-agent -s)"
...从ssh-agent
读取输出并在当前shell中运行它(-s
指定与Bourne兼容的输出,与csh相比)。
如果您使用的是Python,请务必使用pipes.quote()
(或者,对于Python 3.x,shlex.quote()
)安全地处理输出:
import pipes
dirname='/path/to/directory with spaces'
foo_val='value with * wildcards * that need escaping and \t\t tabs!'
print 'cd %s; export FOO=%s;' % (pipes.quote(dirname), pipes.quote(foo_val))
......因为粗心使用否则会导致炮弹攻击。
相比之下,如果您在bash中将其写为外部脚本,请务必使用printf %q
进行安全转义(但请注意,其输出的目标是其他bash shell,而不是POSIX sh合规性) :
#!/bin/bash
dirname='/path/to/directory with spaces'
foo_val='value with * wildcards * that need escaping and \t\t tabs!'
printf 'cd %q; export FOO=%q;' "$dirname" "$foo_val"
如果从您的问题中看起来,您希望出现的命令被写为本机shell函数,我建议将其包装在一个中(这种做法也可以用于{ {1}})。例如,安装可能涉及将以下内容放入command_not_found_handle
:
.bashrc
...这样,用户无需输入my_command() {
eval "$(command /path/to/my_command.py "$@")"
}
。
答案 1 :(得分:1)
基本上,查尔斯达菲击中了头部的钉子,我在这里提出了另一个问题。
你基本上要问的是进程间通信:你有一个进程,它可能是也可能不是shell的子进程(我不认为这太重要了),你想要那个将信息传递给原始shell(只是另一个进程,顺便说一句),让它改变状态。
一种可能性是使用信号。例如,在shell中,您可以:
trap 'cd /tmp; pwd;' SIGUSR2
现在:
这就是通信渠道的一个例子。魔鬼当然是细节。你的问题有两半:如何让shell与你的程序进行通信(如果这对你有用,command_not_found_handle会很好地完成),以及如何让你的程序与shell通信。下面,我将讨论后一个问题:
例如,你可以在原始shell中有一个trap语句:trap 'eval $(/path/to/my/fancy/command $(pwd) $$)' SIGUSR2
...您的花哨命令将被赋予原始shell的当前工作目录作为第一个参数,以及shell的进程ID(因此它知道发出信号的人),并且它可以对其进行操作。如果您的命令将可执行shell命令字符串发送到eval命令,它将在原始shell的环境中执行。
例如:
trap 'eval $(/tmp/doit $$ $(pwd)); pwd;' SIGUSR2
/ tmp / doit是花哨的命令。它可以是任何可执行类型[Python,C,Perl等],关键是它吐出一个shell可以评估的字符串。在/ tmp / doit中,我提供了一个bash脚本:
#!/bin/bash
echo "echo PID: $1 original directory: $2; cd /tmp"
(我确保该文件可执行:chmod 755 / tmp / doit)。现在,如果我输入:
cd; echo $$
然后,在另一个shell中,通过上面的echo获取数字输出(" NNNNN")并执行:
kill -s SIGUSR2 NNNNN
...突然之间,我会在原始shell中看到这样的内容:
PID: NNNNN original directory: /home/myhomepath
/tmp
如果我输入" pwd"在我原来的shell中,我会看到我在/ tmp。
希望command_not_found_handle在当前shell环境中执行某些操作的人可能已经使用信号来获得他想要的效果。在这里我手动运行了kill,但没有理由为shell函数做不到。
在前端做一些奇特的工作,你重新解释或预先解释用户对shell的输入,可能要求用户运行一个非常复杂的前端程序,这取决于你想要什么去做。旧学校"期待"程序是这样的事情的理想选择,但这些天没有太多的年轻人选择TCL :-)。