在 C 程序中,我可以编写 argv[0] 并且新名称显示在 ps 列表中。
我怎样才能在 bash 中做到这一点?
您可以在运行新程序时通过exec -a <newname>
.
只是为了记录,即使它没有完全回答原始发帖人的问题,这也是微不足道的事情zsh
:
ARGV0=emacs nethack
我有机会浏览了 bash 的源代码,但看起来不支持写入 argv[0]。
我假设您有一个希望执行的 shell 脚本,这样脚本进程本身就有一个新的argv[0]
. 例如(我只在 bash 中对此进行了测试,所以我正在使用它,但这可能适用于其他地方)。
#!/bin/bash
echo "process $$ here, first arg was $1"
ps -p $$
输出将是这样的:
$ ./script arg1
process 70637 here, first arg was arg1
PID TTY TIME CMD
70637 ttys003 0:00.00 /bin/bash ./script arg1
所以ps
显示了外壳,/bin/bash
在这种情况下。现在尝试您的交互式外壳exec -a
,但在子外壳中,这样您就不会吹走交互式外壳:
$ (exec -a MyScript ./script arg1)
process 70936 here, first arg was arg1
PID TTY TIME CMD
70936 ttys008 0:00.00 /bin/bash /path/to/script arg1
哎呀,还在显示/bin/bash
。发生了什么?exec -a
可能确实 set ,但是由于argv[0]
操作系统#!/bin/bash
在脚本顶部读取,因此启动了一个新的 bash 实例。好的,如果我们以某种方式在脚本中执行 exec'ing 会怎样?首先,我们需要某种方法来检测这是脚本的“第一次”执行,还是第二个exec
ed 实例,否则第二个实例将再次执行,并在无限循环中不断循环。接下来,我们需要可执行文件不是#!/bin/bash
顶部有一行的文件,以防止操作系统更改我们想要的 argv[0]。这是我的尝试:
$ cat ./script
#!/bin/bash
__second_instance="__second_instance_$$"
[[ -z ${!__second_instance} ]] && {
declare -x "__second_instance_$$=true"
exec -a MyScript "$SHELL" "$0" "$@"
}
echo "process $$ here, first arg was $1"
ps -p $$
多亏了这个答案__second_instance_$$
,我首先根据 PID(不会更改)测试环境变量,exec
这样它就不会与使用此技术的其他脚本发生冲突。如果它是空的,我假设这是第一个实例,然后我导出该环境变量,然后执行。但是,重要的是,我不执行此脚本,而是直接执行 shell 二进制文件,将此脚本 ( $0
) 作为参数,同时传递所有其他参数 ( $@
)。环境变量有点像黑客。
现在输出是这样的:
$ ./script arg1
process 71143 here, first arg was arg1
PID TTY TIME CMD
71143 ttys008 0:00.01 MyScript ./script arg1
那几乎就在那里。argv[0]
就像MyScript
我想要的那样,但是那里有额外的 arg ,./script
这是直接执行 shell(而不是通过操作系统的#!
处理)的结果。不幸的是,我不知道如何得到比这更好的。
Bash 5.0 更新
看起来 Bash 5.0 增加了对写入特殊变量BASH_ARGV0的支持,所以这应该变得更容易完成。
(见发布公告)
( exec -a foo bash -c 'echo $0' )
ps
和其他人检查两件事,其中没有一个是 argv0:(/proc/PID/comm
对于“进程名称”)和/proc/PID/cmdline
(对于命令行)。分配给 argv0 不会更改列ps
中显示的内容CMD
,但会更改进程通常将其视为自己的名称(例如,在输出消息中)。
要更改CMD
列,请写入/proc/PID/comm
:
echo -n mynewname >/proc/$$/comm; ps
您不能以/proc/PID/cmdline
任何方式写入或修改。
Process can set their own "title" by writing to the memory area in which argv
& envp
are located (note that this is different than setting BASH_ARGV0
). This has the side effect of changing /proc/PID/cmdline
as well, which is what some daemons do in order to prettify (hide?) their command lines. libbsd's setproctitle()
does exactly that, but you cannot do that in Bash without support of external tools.
我只想补充一点,这在运行时必须是可能的,至少在某些环境中是这样。在 Linux 上的 perl 中分配 $0 确实会改变 ps 中显示的内容。但是,我不知道这是如何实现的。如果我能找到,我会更新这个。
编辑:基于 perl 是如何做到的,这是不平凡的。我怀疑在运行时是否有内置的方式,但不确定。您可以看到perl 如何在运行时设置进程名称。
将 bash 可执行文件复制到其他名称。
您可以在脚本本身中执行此操作...
cp /bin/bash ./new-name
PATH=$PATH:.
exec new-name $0
如果你试图假装你不是一个 shell 脚本,你可以将脚本本身重命名为很酷的东西,甚至是“”(一个空格),所以
exec new-name " "
将执行 bash 您的脚本并在 ps 列表中显示为new-name
.
好的,所以调用脚本“”是一个非常糟糕的主意:)
基本上就是改名字
bash script
重命名 bash 并重命名脚本。
如果你担心,就像麦克杜姆先生一样。显然,关于将二进制文件复制到新名称(这是完全安全的),您还可以创建一个符号链接
ln -s /bin/bash ./MyFunkyName
./MyFunkyName
这样,符号链接就是出现在 ps 列表中的内容。(再次使用 PATH=$PATH:. 如果你不想要 ./)