コマンドラインでargv [0]を変更する

コマンドラインでargv [0]を変更する

私は数年(数十年)前に次のように話すことができるシステムを使用していたことを覚えています。

$ realname:newname A B C

そしてプログラムはと呼ばれますargv = { "newname", "A", "B", "C" }

ところで、それが何の殻だったかは覚えていません。

この機能は現在シェルに存在しますか?

修正する:

exec -aこれは私が望むように見えますが、プログラムの言語によっては一貫性のない動作が発生します(例えば、間違ったコードであることを知っています)。

$ cat argv.c  && cc argv.c
int main(int argc, char **argv) { printf("<< %s >>\n", argv[0]); }

$ (exec -a fake ./a.out)
<< fake >>

「C」ではうまく機能しますが、Pythonでは機能しません。

$ cat argv.py
#!/usr/bin/python3
import sys
print("<<", sys.argv[0], ">>")

$ (exec -a fake ./argv.py)
<< /home/ray/test/argv.py >>

答え1

zsh(1990年に初めて出版された後):

$ ARGV0="new value for ps's argv[0]" ps -f
UID          PID    PPID  C STIME TTY          TIME CMD
stephane   45193    2195  0 12:08 pts/11   00:00:00 /bin/zsh
stephane   45510   45193  0 12:15 pts/11   00:00:00 new value for ps's argv[0] -f

zsh辞書-コマンドを開始する組み込みコマンドもあります(ログインシェルでシェルを起動するために使用されます)。-argv[0]

$ - ps -f
UID          PID    PPID  C STIME TTY          TIME CMD
stephane    2221    2195  0 06:21 pts/4    00:00:01 /bin/zsh
stephane   46537    2221  0 12:42 pts/4    00:00:00 -ps -f

ksh(1993年から)、bash(1996年2.0から)、扱いにくい(2008 4.3.5以降)、bosh(2015-08-27以降)、mksh(2016 R52c以降)、busybox ash(1.27.0(2017)以降)少なくとも:

$ (exec -a "new value for ps's argv[0]" ps -f)
UID          PID    PPID  C STIME TTY          TIME CMD
stephane    2221    2195  0 06:21 pts/4    00:00:01 /bin/zsh
stephane   46558    2221  0 12:43 pts/4    00:00:00 new value for ps's argv[0] -f

そしてperl

$ perl -e 'exec {shift} @ARGV' /bin/ps "new value for ps's argv[0]" -f
UID          PID    PPID  C STIME TTY          TIME CMD
stephane   46585    2195  0 12:44 pts/14   00:00:00 /bin/zsh
stephane   46646   46585  0 12:45 pts/14   00:00:00 new value for ps's argv[0] -f

そしてpython

$ python3 -c 'import os; import sys; os.execvp(sys.argv[1], sys.argv[2:])' ps "new value for ps's argv[0]" -f 
UID          PID    PPID  C STIME TTY          TIME CMD
stephane   46585    2195  0 12:44 pts/14   00:00:00 /bin/zsh
stephane   46985   46585  0 12:53 pts/14   00:00:00 new value for ps's argv[0] -f

execve()ただし、システムコールを使用して次に始まるスクリプトを実行するときは注意してください。

#! /path/to/interpreter optional-arg

シェルボーンとして:

execve("/path/to/script", ["arg0", "arg1", ...], env)

システムはそれを次に変換します。

execve("/path/to/interpreter", [something, "optional-arg", "/path/to/script", "arg1", ...], env)

存在とともにsomethingシステムによって異なるまたは(Linuxではe /path/to/interpreterargv0

インタプリタがAPIに引数リストを公開すると、パラメータリストも公開されます。スクリプト、いいえ通訳したがって、$0/が一番上にsys.argv[0]表示されませんが。something/path/to/script

答え2

インラインスクリプトを実行するオプションを使用してシェルを起動すると、-c最初の引数は次の場所に配置されます$0

$ sh -c 'printf "0: %s\n" "$0"; printf "Other: %s\n" "$@"'  hello there how are you
0: hello
Other: there
Other: how
Other: are
Other: you

からbashに割り当てると、現在のシェルの値BASH_ARGV0が変更されます。$0

$ printf '%s\n' "$0"
/usr/local/bin/bash
$ BASH_ARGV0="hello"
$ printf '%s\n' "$0"
hello

(しかし、私のシステムのプロセス名は変わりません)

以下を使用して他のパラメータを変更できますset

$ printf '%s\n' "$@"

$ set -- A B C
$ printf '%s\n' "$@"
A
B
C

答え3

ほとんどのシステムではシンボリックリンクで十分です。

~$ cat test.c 
#include <stdio.h>

int main(int ac, char **av)
{
    printf("%s\n", av[0]);
}
~$ cc -o test test.c
~$ ./test 
./test
~$ ln -s test coincoin 
~$ ./coincoin 
./coincoin

busyboxこれは、1つのバイナリのみを使用して複数のユーティリティ(ping、ルーティングなど)を実装するメカニズム(組み込みシステムで広く使用されています)です。

答え4

完全性のために、FreeBSDポートにはargv0バージョン7.1(2009)からこのコマンドがあることがわかります。

関連情報