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
と&
うまくいかない?
Systemdサポートを備えたまともなディストリビューションを実行している場合、最も簡単で技術的に最も安全な方法は device unit を使用することです。
このようにして、systemdは長時間実行スクリプトを完全に制御し、デバイスがシャットダウン/削除されるとプロセスを適切に終了することもできます-プロセスを切り離すと、プロセス状態の完全な制御を放棄することになりますそしてその歴史。
さらに、systemctl status my-ppp-thing.device
を実行すると、デバイスとそれに接続されているサービスのステータスを確認できます。
その他の例と詳細については、 このブログ投稿 も参照してください。
現在、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で正常に動作します。
私はそれを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で実行を続けます。
おそらく、その親プロセスが終了し、終了シグナルがその子に伝播し、子プロセスがブロックされないためです(SIGKILL
の場合は、ブロックすることもできません)。