如何在 bash 中更改 argv0 以便命令在 ps 中显示不同的名称?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3251550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:20:01  来源:igfitidea点击:

How to change argv0 in bash so command shows up with different name in ps?

bashargvps

提问by bstpierre

In a C program I can write argv[0] and the new name shows up in a ps listing.

在 C 程序中,我可以编写 argv[0] 并且新名称显示在 ps 列表中。

How can I do this in bash?

我怎样才能在 bash 中做到这一点?

采纳答案by bstpierre

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].

我有机会浏览了 bash 的源代码,但看起来似乎不支持写入 argv[0]。

回答by Ignacio Vazquez-Abrams

You can do it when running a new program via exec -a <newname>.

您可以在通过exec -a <newname>.

回答by Vincent Fourmond

Just for the record, even though it does not exactly answer the original poster's question, this is something trivial to do with zsh:

只是为了记录,即使它没有完全回答原始海报的问题,但这与zsh以下无关紧要:

ARGV0=emacs nethack

回答by Patrick

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).

我假设您有一个希望执行的 shell 脚本,这样脚本进程本身就有一个新的argv[0]. 例如(我只在 bash 中测试过这个,所以我正在使用它,但这可能在其他地方工作)。

#!/bin/bash

echo "process $$ here, first arg was "
ps -p $$

The output will be something like this:

输出将是这样的:

$ ./script arg1
process 70637 here, first arg was arg1
  PID TTY           TIME CMD
70637 ttys003    0:00.00 /bin/bash ./script arg1

So psshows the shell, /bin/bashin this case. Now try your interactive shell's exec -a, but in a subshell so you don't blow away the interactive shell:

在这种情况下ps,因此显示了外壳/bin/bash。现在试试你的交互式 shell 的exec -a, 但在一个子shell中,这样你就不会吹走交互式 shell:

$ (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

Woops, still showing /bin/bash. what happened? The exec -aprobably did set argv[0], but then a new instance of bash started because the operating system read #!/bin/bashat 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, execed instance, otherwise the second instance will exec again, and on and on in an infinite loop. Next, we need the executable to notbe a file with a #!/bin/bashline at the top, to prevent the OS from changing our desired argv[0]. Here's my attempt:

哎呀,还在显示/bin/bash。发生了什么?在exec -a大概也设定argv[0],但随后的bash的新实例启动,因为操作系统读取#!/bin/bash你的脚本的顶部。好的,如果我们以某种方式在脚本中执行执行会怎样?首先,我们需要一些方法来检测这是脚本的“第一次”执行,还是第二个execed 实例,否则第二个实例将再次执行,并在无限循环中继续执行。接下来,我们需要可执行文件不是#!/bin/bash顶部有一行的文件,以防止操作系统更改我们想要的 argv[0]。这是我的尝试:

$ cat ./script
#!/bin/bash

__second_instance="__second_instance_$$"
[[ -z ${!__second_instance} ]] && {
  declare -x "__second_instance_$$=true"
  exec -a MyScript "$SHELL" "
$ ./script arg1
process 71143 here, first arg was arg1
  PID TTY           TIME CMD
71143 ttys008    0:00.01 MyScript ./script arg1
" "$@" } echo "process $$ here, first arg was " ps -p $$

Thanks to this answer, I first test for the environment variable __second_instance_$$, based on the PID (which does not change through exec) 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.

多亏了这个答案,我首先测试了环境变量__second_instance_$$,基于 PID(它不会改变exec),这样它就不会与使用这种技术的其他脚本发生冲突。如果它是空的,我假设这是第一个实例,然后导出该环境变量,然后 exec。但是,重要的是,我不执行此脚本,而是直接执行 shell 二进制文件,使用此脚本 ( $0) 作为参数,同时传递所有其他参数 ( $@)。环境变量有点像黑客。

Now the output is this:

现在输出是这样的:

( exec -a foo bash -c 'echo 
cp /bin/bash ./new-name
PATH=$PATH:.
exec new-name 
exec new-name " "
' )

That's almost there. The argv[0]is MyScriptlike I want, but there's that extra arg ./scriptin 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.

差不多就这样了。该argv[0]MyScript像我想要的,但有额外的ARG./script在那里是直接执行壳(而不是通过操作系统的的结果#!处理)。不幸的是,我不知道如何比这更好。

Update for Bash 5.0

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.

看起来 Bash 5.0 增加了对写入特殊变量BASH_ARGV0 的支持,所以这应该变得更容易实现。

(see release announcement)

(见发布公告

回答by joe

bash script

回答by frankc

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.

我只想补充一点,这在运行时必须是可能的,至少在某些环境中是这样。在 Linux 上的 perl 中分配 $0 确实会改变 ps 中显示的内容。但是,我不知道这是如何实施的。如果我能找到,我会更新这个。

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.

编辑:基于 perl 如何做到这一点,这很重要。我怀疑在运行时是否有任何内置方式,但不确定。您可以看到perl 如何在运行时设置进程名称

回答by teknopaul

Copy the bash executable to a different name.

将 bash 可执行文件复制到其他名称。

You can do this in the script itself...

您可以在脚本本身中执行此操作...

ln -s /bin/bash ./MyFunkyName
./MyFunkyName

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

如果你试图假装你不是一个 shell 脚本,你可以将脚本本身重命名为一些很酷的东西,甚至是“”(一个空格),这样

##代码##

Will execute bash your script and appears in the ps list as just new-name.

将执行 bash 您的脚本并在 ps 列表中显示为new-name.

OK so calling a script " " is a very bad idea :)

好的,所以调用脚本“”是一个非常糟糕的主意:)

Basically, to change the name

基本上,要更改名称

##代码##

rename bash and rename the script.

重命名 bash 并重命名脚本。

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 ./)

这样,符号链接就会出现在 ps 列表中。(再次使用 PATH=$PATH:. 如果你不想要 ./)