web-dev-qa-db-ja.com

Udevイベントで長時間プロセスを実行するにはどうすればよいですか?

USBモデムが接続されているときにppp接続を実行したいので、次のudevルールを使用します。

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="16d8",\
    RUN+="/usr/local/bin/newPPP.sh $env{DEVNAME}"

(私のモデムは/dev なので ttyACM0

newPPP.sh:

#!/bin/bash
/usr/bin/pon prov $1 >/dev/null 2>&1 &

問題:

udevイベントが発生し、newPPP.shが実行されていますが、newPPP.shプロセスは、4〜5秒後に強制終了されます。 pppには接続する時間がありません(タイムアウトはダイヤルアップで10秒です)。

どうすれば殺されない長い時間のプロセスを実行できますか?

Nohupを使ってみましたが、うまくいきませんでした。

システム:Arch Linux

更新

maxschlepzig のおかげで、解決策 here を見つけました。

私が使う at now udevプロセスから切り離されたジョブを実行します。

しかし、1つの質問は未解決のままです:なぜNohup& うまくいかない?

11
neclude

Systemdサポートを備えたまともなディストリビューションを実行している場合、最も簡単で技術的に最も安全な方法は device unit を使用することです。

このようにして、systemdは長時間実行スクリプトを完全に制御し、デバイスがシャットダウン/削除されるとプロセスを適切に終了することもできます-プロセスを切り離すと、プロセス状態の完全な制御を放棄することになりますそしてその歴史。

さらに、systemctl status my-ppp-thing.deviceを実行すると、デバイスとそれに接続されているサービスのステータスを確認できます。

その他の例と詳細については、 このブログ投稿 も参照してください。

11
Elias Probst

現在、udevはcgroupを使用して、生成されたタスクをシークアンドデストロイします。 1つの解決策は、「現時点」または「バッチ」を使用することです。別の解決策は double fork を実行し、プロセスを別のcgroupに「再配置」することです。これは例ですpythonコード(同様のコードは任意の言語で記述できます):

os.closerange(0, 65535)  # just in case
pid = os.fork()
if not pid:
  pid = os.fork()  # fork again so the child would adopted by init
  if not pid:
    # relocate this process to another cgroup
    with open("/sys/fs/cgroup/cpu/tasks", "a+") as fd:
      fd.write(str(os.getpid()))
    sleep(3)  # defer execution by XX seconds
    # YOUR CODE GOES HERE
sleep(0.1)  # get forked process chance to change cgroup

デバッグ出力は、syslogなどに送信できます。

シェルには、バックグラウンドでコマンドを実行する機能があります。

(

lots of code

) &

アンパーサンドで中括弧でグループ化されたコマンドは、サブシェルで非同期に実行されます。これを使用して、USBモデムを挿入して切り替えたときに自動接続します。約20秒かかり、udevで正常に動作します。

2
user42295

私はそれをsetsidで動作させるようにしました。 udevルールのRUN部分:

RUN+="/bin/bash script.sh"

その後、スクリプトで:

#!/bin/bash
if [ "$1" != "fo_real" ]; then
  /usr/bin/setsid $(/usr/bin/dirname $0)/$(/usr/bin/basename $0) fo_real &
  exit
fi

Rest of script is here....

スクリプトの最初の呼び出しは終了ステータス0で戻りますが、スクリプトの2番目の呼び出しはPPID = 1で実行を続けます。

1
Alives

おそらく、その親プロセスが終了し、終了シグナルがその子に伝播し、子プロセスがブロックされないためです(SIGKILLの場合は、ブロックすることもできません)。

0
peterph