web-dev-qa-db-ja.com

コマンドがpsで異なる名前で表示されるようにbashでargv0を変更するにはどうすればよいですか?

Cプログラムでは、argv [0]と書くことができ、新しい名前がpsリストに表示されます。

どうすればbashでこれを行うことができますか?

23
bstpierre

Bashのソースを調べる機会がありましたが、argv [0]への書き込みがサポートされていないようです。

10
bstpierre

exec -a <newname>を介して新しいプログラムを実行するときにそれを行うことができます。

念のために言っておきますが、元の投稿者の質問に正確に答えているわけではありませんが、これはzshと関係があります。

ARGV0=emacs nethack
10

スクリプトプロセス自体に新しい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はおそらくargv[0]を設定しましたが、オペレーティングシステムがスクリプトの先頭で#!/bin/bashを読み取ったため、bashの新しいインスタンスが開始されました。さて、どういうわけかスクリプト内で実行を実行するとどうなりますか?まず、これがスクリプトの「最初の」実行であるか、2番目のexecedインスタンスであるかを検出する何らかの方法が必要です。そうでない場合、2番目のインスタンスは再び実行され、無限ループで何度も実行されます。次に、OSが目的のargv [0]を変更しないように、実行可能ファイルをnotが上部に#!/bin/bash行を持つファイルにする必要があります。これが私の試みです:

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

この回答 のおかげで、最初に、PID(execを介して変更されない)に基づいて環境変数__second_instance_$$をテストし、衝突しないようにします。この手法を使用する他のスクリプト。空の場合は、これが最初のインスタンスであると想定し、その環境変数をエクスポートしてからexecを実行します。ただし、重要なことに、このスクリプトは実行しませんが、このスクリプト($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ですが、OSの./script処理を介してではなく、シェルを直接実行した結果として、余分な引数#!があります。 )。残念ながら、これよりも良くなる方法がわかりません。

Bash 5.0のアップデート

Bash 5.0は、特別な変数への書き込みのサポートを追加しているようです BASH_ARGV なので、これははるかに簡単に実行できるはずです。

リリース発表 を参照)

7
Patrick
( exec -a foo bash -c 'echo $0' ) 
5
joe

少なくとも一部の環境では、これは実行時に可能でなければならないことを付け加えておきます。 LinuxのPerlで$ 0を割り当てると、psに表示される内容が変わります。しかし、それがどのように実装されているのかわかりません。見つけたら更新します。

編集:Perlがそれを行う方法に基づいて、それは重要です。実行時に途中でバスクが組み込まれているとは思えませんが、確かにはわかりません。 Perlが実行時にプロセス名を設定する方法 を見ることができます。

0
frankc