Linuxサーバーのスクリーンセッション内に長時間実行されているサーバープロセスがあります。少し不安定です(残念ながら私のソフトウェアではないので修正できません!)、安定性のために毎晩プロセスを再起動するスクリプトを作成したいと思います。正常なシャットダウンを行う唯一の方法は、画面プロセスに移動し、実行中のウィンドウに切り替えて、コントロールコンソールに文字列「stop」を入力することです。
Cronjobに毎日停止時刻にその停止コマンドを送信させるために実行できるスマートリダイレクトのゆがみはありますか?
この答えは問題を解決しませんが、30人以上のユーザーが有用だと思ったので、ここに残します、そうでなければ、私はずっと前にそれを削除したでしょう。
/proc/*pid of the program*/fd/0
に書き込みます。 fd
サブディレクトリには、開いているすべてのファイルの記述子が含まれ、ファイル記述子0
は標準入力です(1はstdout、2はstderrです)。
これを使用して、プログラムが実行されているttyにメッセージを出力できますが、プログラム自体に書き込むことはできません。
ターミナル1:
[ciupicri@hermes ~]$ cat
shows on the tty but bypasses cat
ターミナル2:
[ciupicri@hermes ~]$ pidof cat
7417
[ciupicri@hermes ~]$ echo "shows on the tty but bypasses cat" > /proc/7417/fd/0
次のようにサーバーを起動します。
# screen -d -m -S ServerFault tr a-z A-Z # replace with your server
screen はデタッチモードで起動するので、何が起こっているのかを確認したい場合は、次のコマンドを実行します。
# screen -r ServerFault
次のようにサーバーを制御します。
# screen -S ServerFault -p 0 -X stuff "stop^M"
# screen -S ServerFault -p 0 -X stuff "start^M"
# screen -S ServerFault -p 0 -X stuff "^D" # send EOF
(この回答は 分離された画面にテキスト入力を送信する に基づいていますUnix&Linux兄弟サイトから)
説明 パラメータ:
-d -m Start screen in "detached" mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts. -S sessionname When creating a new session, this option can be used to specify a meaningful name for the session. -r [pid.tty.Host] -r sessionowner/[pid.tty.Host] resumes a detached screen session. -p number_or_name|-|=|+ Preselect a window. This is useful when you want to reattach to a specific window or you want to send a command via the "-X" option to a specific window. -X Send the specified command to a running screen session e.g. stuff.
スタッフ [文字列]
Stuff the string string in the input buffer of the current window. This is like the "paste" command but with much less overhead. Without a parameter, screen will Prompt for a string to stuff.
次のようにサーバーを起動します。
# tmux new-session -d -s ServerFault 'tr a-z A-Z' # replace with your server
tmuxがデタッチモードで起動するので、何が起こっているのかを確認したい場合は、次のコマンドを実行します。
# tmux attach-session -t ServerFault
次のようにサーバーを制御します。
# tmux send-keys -t ServerFault -l stop
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault -l start
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault C-d # send EOF
説明 パラメータ:
new-session [-AdDP] [-c start-directory] [-F format] [-n window-name] [-s session-name] [-t target-session] [-x width] [-y height] [Shell-command] Create a new session with name session-name. The new session is attached to the current terminal unless -d is given. window-name and Shell-command are the name of and Shell command to execute in the initial window. If -d is used, -x and -y specify the size of the initial window (80 by 24 if not given). send-keys [-lR] [-t target-pane] key ... (alias: send) Send a key or keys to a window. Each argument key is the name of the key (such as `C-a' or `npage' ) to send; if the string is not recognised as a key, it is sent as a series of characters. The -l flag disables key name lookup and sends the keys literally.
開始するにはこれを試してください:
# screen
# cd /path/to/wd
# mkfifo cmd
# my_cmd <cmd
C-A d
そしてこれは殺すために:
# cd /path/to/wd
# echo "stop" > cmd
# rm cmd
screen
ユーティリティやその他の高度なユーティリティを実行せずに、実行中のプロセスに入力テキストを送信することが可能です。そして、この入力テキストをプロセスの標準入力「ファイル」/proc/PID#/fd/0
に送信することで実行できます。
ただし、入力テキストは、プロセスで読み取るために特別な方法で送信する必要があります。通常のファイルwrite
メソッドを介して入力テキストを送信しても、プロセスはテキストを受信しません。これは、そうすることでその「ファイル」に追加されるだけであり、バイトを読み取るプロセスをトリガーしないためです。
プロセスをトリガーしてバイトを読み取るには、送信されるバイトごとにIOCTL
タイプのTIOCSTI
操作を実行する必要があります。これにより、バイトがプロセスの標準入力キューに配置されます。
これについては、C、Perl、Pythonのいくつかの例で説明します。
-
したがって、ほぼ9年前に尋ねられた元の質問に答えるために、cronジョブは、他の質問に対して人々が書いた例に似たいくつかの小さなユーティリティスクリプト/プログラムを実行する必要があります。質問では、IOCTL
タイプのTIOCSTI
操作を介して5バイトのそれぞれを送信します。
もちろん、これはTIOCSTI
IOCTL
操作タイプ(Linuxなど)をサポートするシステムでのみ機能し、root
ユーザーアカウントからのみ機能します。これらの「ファイル」は/proc/
root
が「所有」しています。
誰かを助ける場合:
同様の問題があり、使用しているプロセスがscreen
またはtmux
にないため、別のアプローチをとる必要がありました。
プロセスが実行されているgdb
にxterm
をアタッチし、gdb
からcall write(5, "stop\n", 5)
を使用してマスターptyファイル記述子に書き込みました。
_/proc/<pid>/fd
_へのリンクを_/dev/ptmx
_で確認し、2つのオプション間で試行錯誤して(一致する両方のファイルに文字列を送信する)、データを送信するファイル記述子を見つけました。記述子は害を引き起こさないようでした)。
私がアタッチしたxterm
プロセスは、キーバインディングからのspawn-new-terminal()
xterm
アクションで生成され、2番目のptmx
ファイル記述子が開いていることがわかりました閉じられていない親ptmx
プロセスのxterm
でした。
したがって、試行錯誤の呼び出しにより、その別の端末に出力が送信されました。
ほとんどのxterm
プロセスには、2つのptmx
ファイル記述子がありません。
これにより、その文字列が端末に効果的に入力されたため、その文字列がその下で実行されているプロセスに送信されました。
n.b.あなたは次のようなもので実行中のプロセスにアタッチできるようにする必要があるかもしれません
_Sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
_
(2010年の)Cristian Ciupituの最も受け入れられた回答にはコメントできないので、これを別の回答に入れなければなりません。
この質問はこのスレッドですでに解決されています: https://stackoverflow.com/questions/5374255/how-to-write-data-to-existing-processs-stdin-from-external-process
要するに:
現在の入力が書き込まれたときにブロックもクローズもしないstdinのパイプでプロセスを開始する必要があります。これは、問題のプロセスにパイプされる単純な無限ループによって実装できます。
$ (while [ 1 ]; do sleep 1; done) | yourProgramToStart
これは、私の場合は機能しなかったパイプを開くためのkrissiの方法とは異なることを確認できます。示されたソリューションは代わりに機能しました。
次に、プロセスの.../fd/0ファイルに書き込み、指示を送信できます。唯一の欠点は、サーバーがシャットダウンした後にエンドレスループを実行しているbashプロセスも終了する必要があることです。