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

发布于 2024-09-09 04:31:23 字数 72 浏览 6 评论 0 原文

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

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

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

How can I do this in bash?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

嗼ふ静 2024-09-16 04:31:23

您可以在通过 exec -a 运行新程序时执行此操作。

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

远山浅 2024-09-16 04:31:23

仅供记录,尽管它没有完全回答原始发帖人的问题,但这对于 zsh 来说是微不足道的:

ARGV0=emacs nethack

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

ARGV0=emacs nethack
雨轻弹 2024-09-16 04:31:23

我有机会浏览 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].

一杯敬自由 2024-09-16 04:31:23

我假设您有一个希望执行的 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 显示 shell,在本例中为 /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

糟糕,仍然显示 /bin/bash。发生了什么? exec -a 可能确实设置了 argv[0],但随后启动了一个新的 bash 实例,因为操作系统读取了 #!/bin/bash code> 在脚本的顶部。好吧,如果我们以某种方式在脚本内执行执行怎么办?首先,我们需要某种方法来检测这是否是脚本的“第一次”执行,还是第二个执行实例,否则第二个实例将再次执行,并无限地执行环形。接下来,我们需要可执行文件不是是顶部带有#!/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) 作为参数,同时传递所有其他参数 ($@ )。环境变量有点hack。

现在的输出是这样的:

$ ./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,所以这应该变得更容易完成。

(请参阅发布公告

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

#!/bin/bash

echo "process $ here, first arg was $1"
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 ps shows the shell, /bin/bash in this case. Now try your interactive shell's exec -a, but in a subshell so you don't blow away the interactive 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 -a probably did set argv[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, execed 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:

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

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.

Now the output is this:

$ ./script arg1
process 71143 here, first arg was arg1
  PID TTY           TIME CMD
71143 ttys008    0:00.01 MyScript ./script arg1

That's almost there. The argv[0] is MyScript 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)

客…行舟 2024-09-16 04:31:23
( exec -a foo bash -c 'echo $0' ) 
( exec -a foo bash -c 'echo $0' ) 
云雾 2024-09-16 04:31:23

ps 和其他人检查两个东西,其中没有一个是 argv0:/proc/PID/comm (用于“进程名称”)和 /proc/PID/ cmdline(用于命令行)。分配给 argv0 不会改变 psCMD 列中显示的内容,但会改变进程通常将其视为自己的名称(例如在输出消息中)。

要更改 CMD 列,请写入 /proc/PID/comm

echo -n mynewname >/proc/$/comm; ps

您无法在任何位置写入或修改 /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 what ps shows in the CMD 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:

echo -n mynewname >/proc/$/comm; ps

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

£冰雨忧蓝° 2024-09-16 04:31:23

我只想补充一点,这在运行时必须是可能的,至少在某些环境中是这样。在 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.

淑女气质 2024-09-16 04:31:23

将 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:. 如果您不需要 ./)

Copy the bash executable to a different name.

You can do this in the script itself...

cp /bin/bash ./new-name
PATH=$PATH:.
exec new-name $0

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

exec new-name " "

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

bash script

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

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

This way, the symlink is what appears in the ps list. (again use PATH=$PATH:. if you dont want the ./)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文