linux – ターミナルからプロセスを完全に切り離すには?

bash linux shell terminal ubuntu

私はUbuntu上でTilda(ドロップダウンターミナル)を私の “コマンドセンター “として使用しています – 他の人がGNOME Do、QuicksilverやLaunchyを使用するかもしれないほとんどの方法

しかし、私はどのようにしてプロセス(例えば Firefox)を起動した端末から完全に切り離すか、つまり、そのような(非)子プロセスを防ぐかで苦労しています

  • は、発信元端末を閉じると終了します
  • 送信元端末をSTDOUT/STDERR経由で “汚染 “する

例えば、「ちゃんとした」ターミナルウィンドウでVimを起動するために、以下のような簡単なスクリプトを試してみました

exec gnome-terminal -e "vim $@" &> /dev/null &

しかし、それではやはり汚染の原因になります(また、ファイル名を渡すとうまくいかないようです)

  333  None  2009-03-23


ベストアンサー

まず第一に、一度プロセスを開始したら、それをバックグラウンドにするには、まずプロセスを停止させ(CtrlZを打つ)、次にbgと入力してバックグラウンドで再開させることができます。これで「ジョブ」となり、stdout/stderr/stdinはまだターミナルに接続されています

プロセスの最後に”& “をつけることで、すぐにバックグラウンドとして処理を開始することができます

firefox &

バックグラウンドで無音で実行するには、これを使用します

firefox </dev/null &>/dev/null &

いくつかの追加情報

nohup は、標準出力/標準出力をファイルに送ることができ、親スクリプトを閉じても子スクリプトを SIGHUP しないように、アプリケーションを実行するためのプログラムです。しかし、アプリケーションを起動する前にこれを使用する先見の明が必要です。nohup の仕組み上、実行中のプロセスに適用することはできません

disown はシェルのジョブリストからシェルのジョブを削除する bash ビルトインです。これは基本的に何を意味するかというと、fg, bgが使えなくなるということですが、より重要なことは、シェルを閉じたときにハングしたり、その子にSIGHUPを送ったりしなくなるということです。nohup とは異なり、disown はプロセスが起動してバックグラウンド化された後に使用されます

できないことは、プロセスを起動した後にプロセスの標準出力/標準出力/標準出力/標準出力/標準出力を変更することです。少なくともシェルからはできません。プロセスを起動して、その標準出力があなたのターミナルであることを伝えた場合 (デフォルトではそれが行われています)、そのプロセスはあなたのターミナルに出力するように設定されています。シェルはプロセスの FD 設定とは何の関係もありません。プロセス自身は標準出力/stderr/stdinを閉じるかどうかを決めることができますが、シェルを使って強制的にそうさせることはできません

バックグラウンドプロセスの出力を管理するために、スクリプトから多くのオプションがあります。しかし、起動したものの消音するのを忘れてしまった対話型プロセス (firefox < /dev/null &>/dev/null &) では、あまり何もできません

GNU screenを入手することをお勧めします。スクリーンを使えば、プロセスの出力が面倒になったときに実行中のシェルを閉じて新しいシェルを開くことができます (^Ac)


あ、ちなみに「$@」を使っているところで「$@」を使うのはやめましょう

$@は、$1, $2, $3 …という意味で、コマンドはこれになります

gnome-terminal -e "vim $1" "$2" "$3" ...

e は引数を一つしか取らないので、これはおそらくあなたが望んでいるものではないでしょう。$1 を使って、スクリプトが一つの引数しか扱えないことを示してください

あなたが与えたシナリオ(gnome-terminal -eで)で複数の引数を正しく動作させるのは本当に難しいです。引数を一つにエンコードしなければなりません。最良で最も堅牢な、しかしむしろ不器用な方法は、このようなものです

gnome-terminal -e "vim $(printf "%q " "$@")"

379  lhunath  2009-03-23


nohup cmd &

nohupはプロセスを完全に切り離します(デーモン化)

209  dsm  2009-03-23


bash(1) を参照してください

もう一つの方法として、at nowを試してみてはいかがでしょうか。スーパーユーザでない場合は、atの使用許可が制限されている可能性があります

66  Randy Proctor  2009-03-23


これらの回答を読んで、私は最初、nohup <command> &を発行すれば十分だと思っていました。gnome-terminal で zsh を実行してみると、nohup <command> & はシェルが終了時に子プロセスを殺すのを防げないことがわかりました。nohup は特に非対話型のシェルでは便利ですが、SIGHUP シグナルに対して子プロセスがハンドラをリセットしない場合にのみ、この動作が保証されます

私の場合、nohupはハングアップシグナルがアプリケーションに到達するのを防ぐべきでしたが、子アプリケーション(この場合はVMWare Player)はSIGHUPハンドラをリセットしていました。その結果、ターミナルエミュレータが終了したときに、サブプロセスを殺すことができました。これは、私の知る限りでは、シェルのジョブテーブルからプロセスを削除することによってのみ解決できます。nohup がシェルの組み込み関数でオーバーライドされている場合は、これで十分かもしれませんが、そうでない場合は


disownは、bashzshksh93に組み込まれたシェルです

<command> &
disown

or

<command> &; disown

を使用してください。これは、ジョブテーブルからサブプロセスを削除するという一般的に望ましい効果を持っています。これにより、誤って子プロセスにシグナルを送ることなくターミナルエミュレータを終了することができます。SIGHUP ハンドラがどのように見えようとも、これは子プロセスを殺してはいけません

しかし、ターミナルエミュレータが終了した後、initプロセスに接続されているのを見ることができるはずです。言い換えれば、すべてが本来あるべき姿であり、おそらくあなたが望んでいる通りになっているということです

お使いのシェルが disown をサポートしていない場合はどうすればいいのでしょうか?サポートしているシェルに切り替えることを強く推奨しますが、サポートしていない場合、いくつかの選択肢があります

  1. screentmuxはこの問題を解決することができますが、それらははるかに重いソリューションであり、私はそのような単純なタスクのためにそれらを実行しなければならないのが嫌いです。これらは、一般的にリモートマシン上で tty をメンテナンスしたい場合には、より適しています
  2. 多くのユーザにとって、シェルが zsh の setopt nohup のような機能をサポートしているかどうかを確認することが望ましいかもしれません。これは、シェル終了時にジョブテーブルのジョブに SIGHUP を送信しないように指定するために使うことができます。シェルを終了する直前にこれを適用するか、常にオンにしておきたい場合は ~/.zshrc のようにシェルの設定に追加してください
  3. ジョブテーブルを編集する方法を探す。tcshcshでは方法が見つからず、なんだか気になります
  4. フォークオフとexec()を行う小さなC言語のプログラムを書く。これは非常に貧弱な解決策ですが、ソースは数十行で構成されているはずです。コマンドをコマンドライン引数としてCプログラムに渡すことができるので、ジョブテーブルのプロセス固有のエントリを避けることができます

44  Stephen Rosen  2014-01-22


  1. nohup $COMMAND &
  2. command & disownします
  3. setsid command

私は2番をずっと使ってきましたが、3番でも十分に動作します。また、disownnohupのフラグが-hになっていて、-aですべてのプロセスをdisownでき、-arで実行中のすべてのプロセスをdisownできるようになっています

サイレンシングは$COMMAND &>/dev/nullによって達成される

これが役に立つことを願っています

33  Mr. Minty Fresh  2015-08-25


バッシュの最もシンプルで唯一の正解

command & disown

ターミナルからプロセスを切り離す必要はありませんが、シェルから切り離す必要はありません

10  ManuelSchneid3r  2017-05-05


スクリーンで解決できるかもしれませんね

9  None  2009-03-25


を使うと、プロセスを切り離すために括弧を使うことができます

Compare this:

> jobs # shows nothing
> firefox &
> jobs
[1]  + Running                       firefox

To this:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

これにより、ジョブリストから firefox が削除されますが、ターミナルにはまだ縛られています

9  Nathan Fellman  2009-03-23


ttyシェルを切り離すには、サブシェルからコマンドを実行してください

(command)&

終了時に使用していた端末が終了したが、プロセスが生きている場合

check –

(sleep 100) & exit

他の端末を開く

ps aux | grep sleep

プロセスはまだ生きている

8  jitendra  2012-08-07


ジョブのバックグラウンドとフォアグラウンドは、おそらくすべての Unix システム管理者が最初に知っておくべきことの一つでしょう

bashを使った方法をご紹介します

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg

5  djangofan  2013-05-22


あなたはnohupコマンドを使用してコマンドを実行することができます、これはあなたのプロセスを切り離し、指定されたファイルに出力をリダイレクトします…しかし、私はそれが正確にあなたが必要とするものであるかどうかを確認していません

4  Ben  2009-03-23


これを bashrc/zshrc に追加するだけです

detach() {
"$@" 1>/dev/null 2>/dev/null &; disown
}

そうすると、このように勘当されたコマンドを実行することができます

detach gedit ~/.zshrc

3  B. Branchard  2018-02-05


daemonを試してみてください

2  Volker Stolz  2009-03-23


私の.bashrcには、まさにその目的のためにこれらの関数があります

function run_disowned() {
"$@" & disown
}

function dos() {
# run_disowned and silenced

run_disowned "$@" 1>/dev/null 2>/dev/null
}

コマンドの前にdosを付けて、ターミナルから切り離して実行します

この関数は、bashzshで動作するように書かれています

1  mic_e  2015-06-14


kde-cli-tools パッケージで利用可能なKDEのkstart5が役立ちます

kstart5 my-command &

guiを実行していれば、xウィンドウの複数のアスペクトを管理することも可能です


ソース。Linuxhacks.org ディスクロージャー: 私は Linuxhacks.org

の所有者です

1  intika  2020-05-02


Mac OS Xでは、ターミナルで子プロセスが引き裂かれないようにするには、nohup AND disownの両方を使う必要があることがわかりました

0  aaron  2010-06-19


私は以下のスクリプトを使っています。端末への印刷処理を停止し、nohupでデタッチし、TIMEOUTの範囲内でコマンドが終了するとリターンステータスで終了します

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#use nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send nohup's output to /dev/null, supressing nohup.out
#run nohup in the background so this script doesn't block
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/dev/null 2>&1 &
NOHUP_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $NOHUP_PID
NOHUP_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $NOHUP_STATUS != 0 ] && echo "Error: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Usage example:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>

0  jozxyqk  2014-09-21


sudo apt install ucommon-utils

pdetach command

これでいいですよ 🙂

0  d4rk4ng31  2019-06-21


現在の SSH セッションからプログラムを完全に切り離すには、run を実行します

setsid nohup script.sh &

そして、すべてのログ (stderr & stdout) をリダイレクトするには、以下のように実行します

setsid nohup script.sh &>/tmp/script.log &

プロセスが detache を受けたかどうかを二重に確認するには、次のように実行してください:

ps -efj --forest

そして、階層的なプロセス ツリーを見てください

0  Nikolas  2020-08-12


多くの回答はnohupを使用することを示唆しています。私はむしろ pm2 を使うことをお勧めします。nohup よりも pm2 を使うことで、アプリケーションを生きたまま維持したり、アプリケーションのログファイルを維持したり、他の多くの機能を利用したりと、多くの利点があります。詳細については、これをチェックアウト

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

-1  haccks  2017-02-15


もしあなたの目的が、ターミナルウィンドウを囲わずに単にコマンドラインアプリケーションを起動することであるならば、ターミナルを起動した後にalt-F2でアプリケーションを実行してみるといいかもしれません

-1  MattKelly  2017-04-05


タイトルとURLをコピーしました