6

#! を使用する正当な 理由はたくさんあります。/usr/bin/env. 結論: コードの移植性が向上します。そうですね。これをチェックしてください....


ほぼ同一のスクリプトが 2 つあり、bintest.py

#! /usr/bin/python
import time
time.sleep(5*60)

envtest.py

#! /usr/bin/env python
import time
time.sleep(5*60)

それらはシバンのみが異なることに注意してください。


bintest.py期待どおりに実行されます

br@carina:~$ ./bintest.py & ps && killall bintest.py
[1] 15061
  PID TTY 時間コマンド
14625 ポイント/0 00:00:00 バッシュ
15061 ポイント/0 00:00:00 bintest.py
15062 ポイント/0 00:00:00 ps
br@carina:~$
[1]+ ./bintest.py を終了しました

しかし、envtest.py最適とは言えないことをします

br@carina:~$ ./envtest.py & ps && killall envtest.py
[1] 15066
  PID TTY 時間コマンド
14625 ポイント/0 00:00:00 バッシュ
15066 ポイント/0 00:00:00 パイソン
15067 ポイント/0 00:00:00 ps
envtest.py: プロセスが見つかりません
br@carina:~$ killall python
br@carina:~$
[1]+ ./envtest.py を終了しました

私たちが見たのは、を使用#! /usr/bin/envすると、プロセスが「envtest.py」ではなく「python」という名前を受け取るため、killall効果がなくなったことです。あるレベルでは、ある種の移植性を別の移植性と交換したように見えます: Python インタープリターを簡単に交換できるようになりましたが、コマンド ラインでの "kill-ability" が失われました。どうしたの?両方を達成するためのベスト プラクティスがあるとすれば、それは何ですか?

4

4 に答える 4

2

コマンド ラインの「kill-ability」は、$!シェル変数から取得したバックグラウンド プロセスの PID を使用して、移植可能かつ確実にアドレス指定できます。

$ ./bintest.py & bg_pid=$! ; echo bg_pid=$bg_pid ; ps && kill $bg_pid
[1] 2993
bg_pid=2993
  PID TTY          TIME CMD
 2410 pts/0    00:00:00 bash
 2993 pts/0    00:00:00 bintest.py
 2994 pts/0    00:00:00 ps
$ 
[1]+  Terminated              ./bintest.py
$ 

および envtest.py

$ ./envtest.py & bg_pid=$! ; echo bg_pid=$bg_pid ; ps && kill $bg_pid
[1] 3016
bg_pid=3016
  PID TTY          TIME CMD
 2410 pts/0    00:00:00 bash
 3016 pts/0    00:00:00 python
 3017 pts/0    00:00:00 ps
$ 
[1]+  Terminated              ./envtest.py
$ 

@Adam Bryzak が指摘しているように、どちらのスクリプトも Mac OS X でプロセス タイトルを設定しません。そのため、その機能が確実な要件である場合は、アプリケーションで python モジュールsetproctitleをインストールして使用する必要がある場合があります。

この Stackoverflow の投稿では、Python でのプロセス タイトルの設定について説明しています。

于 2012-04-22T02:09:21.833 に答える
0

killallスクリプト名を使用して常に機能することに頼ることはできないと思います。Mac OS XI では、ps両方のスクリプトを実行した後、次の出力が得られます。

 2108 ttys004    0:00.04 /usr/local/bin/python /Users/adam/bin/bintest.py
 2133 ttys004    0:00.03 python /Users/adam/bin/envtest.py

実行killall bintest.py結果は

No matching processes belonging to you were found
于 2011-06-30T03:45:57.813 に答える
0

killall <scriptname>スクリプト言語をクロスプラットフォームでコマンドラインから簡単に監視できるようにするソリューションが欲しいのですが、カスタムサービスを停止するための代替手段を探しているだけの場合は、次のように解決しました。

kill `ps -fC <interpreterName> | sed -n '/<scriptName>/s/^[^0-9]*\([0-9]*\).*$/\1/gp'`

ps と正規表現にあまり慣れていない人のために説明すると、ps-f修飾子は、コマンドライン引数を含む、プロセスに関する「完全な」情報のセットを-C一覧表示し、次のコマンドに一致するコマンドのみに一覧をフィルター処理するように指示します。 -line 引数。orまたは何か<interpreterName>に置き換えます。pythonnode

sed-n引数は、デフォルトでは何も出力しないように指示しており、正規表現スクリプトは、何かを出力したいことを明示的に示す必要があります。

正規表現では、最初の/<scriptName>/行は内部正規表現を含む行のみに結果をフィルタリングするように指示します。たとえば、 に<scriptName>置き換えることができます。envtest

s、置換正規表現が続くことを示します。/^[^0-9]*\([0-9]*\).*$/は行一致部分であり/\1/、置換部分です。行の一致部分で、^最初と$最後の は、一致が行の先頭から開始され、行の最後で終了する必要があることを意味します。つまり、チェックされている行全体が置き換えられます。

使用できる文字のセットを定義するために使用されます[^0-9]*[]正規表現のこの部分では、ダッシュ-は文字の範囲を意味するため、 に展開され0123456789ます。^here は「not」を意味し、すぐに「数字ではない任意の文字に一致する」ことを意味します。後のアスタリスク*は、一致しない文字 (この場合は数字) に遭遇するまで、このセット内の文字を一致させ続けることを意味します。

には との\([0-9]*\)2 つの部分が\(\)あり[0-9]*ます。後者は、前の説明から簡単に理解できるはずです。数字のみに一致し、可能な限り多くを取得します。一致するものの\(\)内容を一時変数に保存する手段。(Javascript や Perl を含む他の RegEx バージョンで()は、代わりに使用されます。)

最後に、可能なすべて.*の文字を意味するように、残りのすべての文字に一致する手段.

この/\1/部分は、行の一致した部分 (この場合は行全体) を\1、保存された一時変数への参照である に置き換えることを示しています (2 つの\(\)セクションがあった場合、RegEx の最初のセクション\1は秒\2)。

その後は、g「貪欲」になり、遭遇したすべての行でこの一致するコードを実行し、pこの時点に到達した行を印刷する手段を意味します。

技術的には、スクリプトの複数のコピーを実行している場合、これは爆発し、実際には少し重いものが必要になります。

ps -fC <interpreterName> | sed -n '/<scriptName>/s/^[^0-9]*\([0-9]*\).$/kill \1/gp' | bash

kill*all* 機能を真に複製したいが、これにより、強制終了したいスクリプトごとに個別の bash シェルが生成される場合。

于 2012-04-17T20:18:20.973 に答える
0

コメントで、問題は、異なるシステム (特に MacOS と Linux) が実行可能ファイルを異なるディレクトリに配置することだと言います。

これを回避するには、両方のシステムで同じフル パスを持つディレクトリを作成し、実行可能ファイルへのシンボリック リンクを作成します。

Ubuntu、Solaris、および Cygwin での実験では、シバンで指定された実行可能ファイルがシンボリック リンクになる可能性があることが示されています。(私は MacOS システムにアクセスできないので、そこで動作するかどうかはわかりません。)

たとえば、私の Ubuntu システムでは次のようになります。

$ cat hello.bash
#!/tmp/bin/bash

echo Yes, it works
$ ./hello.bash
-bash: ./hello.bash: /tmp/bin/bash: bad interpreter: Permission denied
$ mkdir /tmp/bin
$ ln -s /bin/bash /tmp/bin/.
$ ./hello.bash
Yes, it works
$ 

関連するすべてのシステムに共通ディレクトリを設定するのは、明らかに不便です。(/tmpこの例で使用しました。別の場所の方がよい場合があります。)

これが とどのように相互作用するかはわかりませんkillallが、試してみる価値はあります。

于 2012-04-17T20:37:28.580 に答える