如何更改 bash 中的 argv0 以便命令在 ps 中显示为不同的名称?
在 C 程序中,我可以编写 argv[0],新名称会显示在 ps 列表中。
我怎样才能在 bash 中做到这一点?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
在 C 程序中,我可以编写 argv[0],新名称会显示在 ps 列表中。
我怎样才能在 bash 中做到这一点?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(8)
您可以在通过 exec -a 运行新程序时执行此操作。
You can do it when running a new program via
exec -a <newname>
.仅供记录,尽管它没有完全回答原始发帖人的问题,但这对于
zsh
来说是微不足道的:Just for the record, even though it does not exactly answer the original poster's question, this is something trivial to do with
zsh
:我有机会浏览 bash 的源代码,看起来不支持写入 argv[0]。
I've had a chance to go through the source for bash and it does not look like there is any support for writing to argv[0].
我假设您有一个希望执行的 shell 脚本,以便脚本进程本身有一个新的
argv[0]
。例如(我只在 bash 中测试过这个,所以我正在使用它,但这可能在其他地方工作)。输出将如下所示:
所以
ps
显示 shell,在本例中为/bin/bash
。现在尝试交互式 shell 的exec -a
,但在子 shell 中,这样就不会破坏交互式 shell:糟糕,仍然显示
/bin/bash
。发生了什么?exec -a
可能确实设置了argv[0]
,但随后启动了一个新的 bash 实例,因为操作系统读取了#!/bin/bash
code> 在脚本的顶部。好吧,如果我们以某种方式在脚本内执行执行怎么办?首先,我们需要某种方法来检测这是否是脚本的“第一次”执行,还是第二个执行实例,否则第二个实例将再次执行,并无限地执行环形。接下来,我们需要可执行文件不是是顶部带有#!/bin/bash
行的文件,以防止操作系统更改我们所需的argv[0] 。这是我的尝试:感谢 这个答案,我首先测试环境变量
__second_instance_$$
,基于 PID(不会通过exec
更改),这样它就不会与使用此技术的其他脚本发生冲突。如果它是空的,我假设这是第一个实例,然后导出该环境变量,然后执行。但重要的是,我不执行此脚本,而是直接执行 shell 二进制文件,并使用此脚本 ($0
) 作为参数,同时传递所有其他参数 ($@ )。环境变量有点hack。
现在的输出是这样的:
差不多就这样了。
argv[0]
是我想要的MyScript
,但是其中有额外的 arg./script
这是执行 shell 的结果直接(而不是通过操作系统的#!
处理)。不幸的是,我不知道如何才能比这更好。Bash 5.0 更新
看起来 Bash 5.0 添加了对写入特殊变量的支持 BASH_ARGV0,所以这应该变得更容易完成。
(请参阅发布公告)
I'm assuming you've got a shell script that you wish to execute such that the script process itself has a new
argv[0]
. For example (I've only tested this in bash, so i'm using that, but this may work elsewhere).The output will be something like this:
So
ps
shows the shell,/bin/bash
in this case. Now try your interactive shell'sexec -a
, but in a subshell so you don't blow away the interactive shell:Woops, still showing
/bin/bash
. what happened? Theexec -a
probably did setargv[0]
, but then a new instance of bash started because the operating system read#!/bin/bash
at the top of your script. Ok, what if we perform the exec'ing inside the script somehow? First, we need some way of detecting whether this is the "first" execution of the script, or the second,exec
ed instance, otherwise the second instance will exec again, and on and on in an infinite loop. Next, we need the executable to not be a file with a#!/bin/bash
line at the top, to prevent the OS from changing our desired argv[0]. Here's my attempt:Thanks to this answer, I first test for the environment variable
__second_instance_$$
, based on the PID (which does not change throughexec
) so that it won't collide with other scripts using this technique. If it's empty, I assume this is the first instance, and I export that environment variable, then exec. But, importantly, I do not exec this script, but I exec the shell binary directly, with this script ($0
) as an argument, passing along all the other arguments as well ($@
). The environment variable is a bit of a hack.Now the output is this:
That's almost there. The
argv[0]
isMyScript
like I want, but there's that extra arg./script
in there which is a consequence of executing the shell directly (rather than via the OS's#!
processing). Unfortunately, I don't know how to get any better than this.Update for Bash 5.0
Looks like Bash 5.0 adds support for writing to special variable BASH_ARGV0, so this should become far simpler to accomplish.
(see release announcement)
ps
和其他人检查两个东西,其中没有一个是 argv0:/proc/PID/comm
(用于“进程名称”)和/proc/PID/ cmdline
(用于命令行)。分配给 argv0 不会改变ps
在CMD
列中显示的内容,但会改变进程通常将其视为自己的名称(例如在输出消息中)。要更改
CMD
列,请写入/proc/PID/comm
:您无法在任何位置写入或修改
/proc/PID/cmdline
方式。进程可以通过写入内存区域来设置自己的“标题”,其中
argv
&envp
位于(请注意,这与设置BASH_ARGV0
不同)。这也会产生更改/proc/PID/cmdline
的副作用,这是某些守护进程为了美化(隐藏?)其命令行而所做的事情。 libbsd 的setproctitle()
正是这样做的,但如果没有外部工具的支持,您就无法在 Bash 中做到这一点。ps
and others inspect two things, none of which is argv0:/proc/PID/comm
(for the "process name") and/proc/PID/cmdline
(for the command-line). Assigning to argv0 will not change whatps
shows in theCMD
column, but it will change what the process usually sees as its own name (in output messages, for example).To change the
CMD
column, write to/proc/PID/comm
:You cannot write to or modify
/proc/PID/cmdline
in any way.Process can set their own "title" by writing to the memory area in which
argv
&envp
are located (note that this is different than settingBASH_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'ssetproctitle()
does exactly that, but you cannot do that in Bash without support of external tools.我只想补充一点,这在运行时必须是可能的,至少在某些环境中是这样。在 Linux 上的 perl 中分配 $0 确实会改变 ps 中显示的内容。然而,我不知道这是如何实施的。如果我能找到,我会更新这个。
编辑:
根据 Perl 的做法,它并不简单。我怀疑运行时是否有内置的 bask,但不确定。您可以看到 perl 如何在运行时设置进程名称。
I will just add that this must be possible at runtime, at least in some environments. Assigning $0 in perl on linux does change what shows up in ps. I do not know how that is implemented, however. If I can find out, i'll update this.
edit:
Based on how perl does it, it is non-trivial. I doubt there is any bask built in way at runtime but don't know for sure. You can see how perl does sets the process name at runtime.
将 bash 可执行文件复制到不同的名称。
您可以在脚本本身中执行此操作...
如果您试图假装自己不是 shell 脚本,您可以将脚本本身重命名为很酷的名称,甚至是“”(单个空格),这样
将执行 bash 您的脚本并出现在ps 列表为
new-name
。好吧,所以调用脚本“”是一个非常糟糕的主意:)
基本上,要更改名称
重命名bash并重命名脚本。
如果你像麦克杜姆先生一样担心。显然是,关于将二进制文件复制到新名称(这是完全安全的),您还可以创建一个符号链接
这样,符号链接就是出现在 ps 列表中的内容。 (再次使用 PATH=$PATH:. 如果您不需要 ./)
Copy the bash executable to a different name.
You can do this in the script itself...
If you are trying to pretend you are not a shell script you can rename the script itself to something cool or even " " (a single space) so
Will execute bash your script and appears in the ps list as just
new-name
.OK so calling a script " " is a very bad idea :)
Basically, to change the name
rename bash and rename the script.
If you are worried, as Mr McDoom. apparently is, about copying a binary to a new name (which is entirely safe) you could also create a symlink
This way, the symlink is what appears in the ps list. (again use PATH=$PATH:. if you dont want the ./)