web-dev-qa-db-ja.com

Linuxでは、SSHクライアントを閉じた後にバックグラウンドプロセスが停止されないようにする方法

私はSSH(PuTTY)を介してLinuxマシンに取り組んでいます。私はプロセスを夜中に実行したままにする必要があるので、私はプロセスをバックグラウンドで開始し(コマンドの最後にアンパサンドを付けて)、標準出力をファイルにリダイレクトすることでそれを実行できると思いました。驚いたことに、それはうまくいきません。 PuTTYウィンドウを閉じるとすぐに、プロセスは停止します。

どうしたらそれを防ぐことができますか?

279
GetFree

" Nohup "プログラムをチェックしてください。

294
JesperE

私は GNU Screen を使うことを勧めます。それはあなたがあなたのプロセスのすべてが実行され続けている間あなたがサーバーから切断することを可能にします。私はそれが存在することを知る前に私はそれなしで生きていた方法がわからない。

163
gpojd

セッションが閉じられると、プロセスはSIGHUPシグナルを受け取りますが、これは明らかに捕捉されていません。これを防ぐために、プロセス起動時にNohupコマンド、またはプロセス開始後にbash組み込みコマンドdisown -hを使用できます。

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the Shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.
78
Robert Gamble

デーモン化する?おっ?画面? (tmux ftw、画面はジャンクです;-)

ダブルフォーク - 最初から他のすべてのアプリがやってきたことをするだけです。

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

バング!完了:-)私はあらゆる種類のアプリや多くの古いマシンでこの無数の時間を使ってきました。あなたはリダイレクトと組み合わせることができ、あなたとプロセスの間にプライベートチャンネルを開くことができます。

Coproc.shとして作成します。

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. Nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

その後

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

そしてそこに行く、何でも産卵する。 <(:)はプロセス置換を介して匿名パイプを開きますが、これは終了しますが、ハンドルを持っているのでパイプは動き続けます。私はたいていsleep 1の代わりに:をやや怠け者なのでやります、そして私は「ファイルビジー」エラーを得ます - 本当のコマンドが実行されても起こらないでしょう(例えばcommand true

"heredocソーシング":

. /dev/stdin <<EOF
[...]
EOF

これは、busybox/etc(initramfs)を含む私が今までに試したすべてのシェルすべてで動作します。私はこれまでにそれが行われたのを見たことがない、私は独自にそれを発見している間に発見した。しかし、そのようなことがあれば、それはしばしばもっと管理しやすい形のevalとして役立ちます。

37
anthonyrisinger
Nohup blah &

あなたのプロセス名をblahに置き換えてください。

33
Brian Knoblauch

個人的には、 'batch'コマンドが好きです。

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

これは背景にそれを詰め込み、そしてあなたに結果をメールで送ります。これはcronの一部です。

17
Will Hartung

他の人が指摘したように、SSHセッションから切断できるようにバックグラウンドでプロセスを実行するには、バックグラウンドプロセスを制御端末から適切に分離する必要があります。これがSSHセッションで使用される疑似端末です。

プロセスのデーモン化に関する情報は、Stevensの "Advanced Network Program、Vol 1、3rd Edn"やRochkindの "Advanced Unix Programming"などの本にあります。

私は最近(ここ数年で)自分自身を適切にデーモン化していなかった反抗的なプログラムに対処しなければなりませんでした。私は、汎用のデーモン化プログラムを作成することによって、それに対処することになりました - Nohupに似ていますが、より多くの利用可能なコントロールがあります。

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

二重ダッシュはGNU getopt()関数を使用しないシステムではオプションです。 Linuxなどでは必要です(あるいは環境でPOSIXLY_CORRECTを指定する必要があります)。

daemonizeのソースが必要な場合は、まだ私に連絡することができます(gmail dot comのfirstname dot lastname)。

しかし、コードは(ついに)私の SOQ (Stack Overflow Questions)リポジトリの packages サブディレクトリのファイルdaemonize-1.10.tgzとしてGitHubで利用可能になりました。

11

Debianベースのシステム(リモートマシン上)にインストールします。

Sudo apt-get install tmux

使用法:

tmux

必要なコマンドを実行する

セッション名を変更するには

Ctrl + B次に$

セット名

セッションを終了するには

Ctrl + B次にD

(これはtmuxセッションを離れます)。その後、SSHからログアウトできます。

また戻ってきたりチェックしたりする必要があるときは、SSHを起動して次のように入力します。

tmux attach session_name

Tmuxセッションに戻ります。

5
Max

詳細をファイルに記録する場合は、Nohupが非常に優れています。しかし、それがバックグラウンドになると、あなたのスクリプトが要求した場合、あなたはそれにパスワードを与えることができません。 screenを試す必要があると思います。そのユーティリティはyumを使ってあなたのLinuxディストリビューションにインストールすることができます。例えばCentOSのyum install screenそしてあなたのシェルタイプscreenでPuTTYか他のソフトウェアを通してあなたのサーバーにアクセスしてください。 PuTTYで画面[0]が開きます。仕事をしなさい。同じPuTTYセッションで、より多くの画面[1]、画面[2]などを作成できます。

あなたが知る必要がある基本的なコマンド:

画面を起動する

画面


c次の画面に移動する

ctrl + a + c


nあなたが作成したext画面に移動する

ctrl + a + n


d etachへ

ctrl + a + d


作業中はあなたのPuTTYを閉じてください。そして次回PuTTYタイプでログインしたとき

screen -r

画面に再接続すると、プロセスがまだ画面上で実行されていることがわかります。画面を終了するには#exitと入力します。

詳細についてはman screenを参照してください。

5
Adeel Ahmad

ほとんどのプロセスでは、この古いLinuxコマンドライントリックを使って擬似デーモン化することができます。

# ((mycommand &)&)

例えば:

# ((sleep 30 &)&)
# exit

それから新しいターミナルウィンドウを起動してください。

# ps aux | grep sleep

sleep 30がまだ実行中であることを示します。

あなたがしたことは子の子としてプロセスを開始することです、そしてあなたが終了するとき、通常終了するプロセスを引き起こすであろうNohupコマンドは孫の子にカスケードしないで、それでも孤立したプロセスとしてそれを残しますランニング。

私はこの "設定して忘れる"アプローチを好みます。Nohupscreen、tmux、I/Oリダイレクション、あるいはそのようなものを扱う必要はありません。

5
RAM

ログアウト時の引数として、Nohupは、親プロセスが強制終了された場合にクライアントプロセスが強制終了されないようにします。さらにもっと良い:

Nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohupを使用すると、SSHセッションとその子プロセスがログアウトしたときに強制終了されるプロセスが、終了しないようになります。私が与えたコマンドはあなたが後でそれを正しく殺してログアウトした後にプロセスを実行できるようにpidファイルにアプリケーションのpidを保存することができる方法を提供します。

5
jcodeninja

Screenを使用してプロセスをrootとして実行する場合は、特権昇格攻撃の可能性に注意してください。自分のアカウントが何らかの形で侵害された場合は、サーバー全体を引き継ぐ直接的な方法があります。

このプロセスを定期的に実行する必要があり、サーバーに十分なアクセス権がある場合は、cronを使用してジョブを実行することをお勧めします。 init.d(スーパーデーモン)を使用してバックグラウンドでプロセスを起動することもできます。また、終了したらすぐに終了することもできます。

5
Dana the Sane

画面を使用してください。使い方はとても簡単で、端末用のvncのように動作します。 http://www.bangmoney.org/presentations/screen.html

4
Deon

この文字列をコマンドに追加してください:>& - 2>& - <& - &。 >& - 標準出力を閉じることを意味します。 2>& - 近い標準エラー出力を意味します。 <& - は標準入力を閉じます。 &はバックグラウンドで実行することを意味します。これはssh経由でプログラム的にジョブを開始するためにも機能します。

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
2
tbc0

Xアプリケーションを実行したい場合は、 xpra を "screen"と一緒に使用してください。

2
Alexey Shurygin

オープンソースのlibslackパッケージの daemon コマンドもあります。

daemonは、かなり設定変更が可能で、自動再起動、ロギング、pidfile処理などの面倒なデーモンに関するすべてのことを考慮しています。

2
janv

私はまた、スクリーンプログラムに行くだろう(私はsome1他の答えがスクリーンだったことを知っているが、これは完成です)

&、ctrl + z bg disown、Nohupなどが、ログオフ時にジョブがまだ強制終了されるという厄介な驚きを与える可能性があるだけではありません。それは私がスクリーンを使用するように切り替えた原因であるが、私は二重フォークが解決するだろうとして私はanthonyrisinger解決策を推測します)、またスクリーンは単にバックグラウンドよりもメジャー利点があります:

screen will background your process without losing interactive control to it

ところで、これは私が最初の場所で尋ねることは決してないだろう質問です:) ...私はすべてのUNIXで何かをやっての私の最初からscreenを使用します...私は(ほとんど)決してscreenを起動せずにunix/linuxシェルで動作しません最初に...そして、私は今やめなければならないか、あるいは私は、良い画面が何であるか、そして何ができるかの無限のプレゼンテーションを始めます...それを自分で調べてください、それは価値があります;)

2
THESorcerer

Systemd/Linuxでは、 systemd-run はセッションに依存しないプロセスを起動するための素晴らしいツールです。言いたい奴には言わせとけ

1
Eugene Shatsky

受け入れられた答えはNohupを使うことを提案します。 pm2 を使うことをお勧めします。 pm2 over Nohupを使うことには、アプリケーションの存続、アプリケーションのログファイルの維持、その他多くの機能など、多くの利点があります。詳細については これをチェックしてください

pm2をインストールするには、ダウンロードが必要ですnpm。 Debianベースのシステム用

Sudo apt-get install npm

そしてRedhatのために

Sudo yum install npm

あるいは、 これらの指示 に従うこともできます。インストールした後npmインストールに使用しますpm2

npm install pm2@latest -g

それが終わったらあなたはあなたのアプリケーションを起動することができます。

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

プロセス監視には、次のコマンドを使用します。

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

アプリ名またはプロセスIDを使用してプロセスを管理するか、すべてのプロセスをまとめて管理します。

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

ログファイルは

$HOME/.pm2/logs #contain all applications logs

バイナリ実行ファイルはpm2を使って実行することもできます。 jasonファイルに変更を加える必要があります。 "exec_interpreter" : "node""exec_interpreter" : "none".に変更します( 属性セクション を参照)。

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

上記のコードをコンパイルする

gcc -o hello hello.c  

そしてバックグラウンドでnp2でそれを実行する

pm2 start ./hello
1
haccks

スクリーンコマンドを使いました。このリンクにはこれを行う方法についての詳細があります

https://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/#starting

1