web-dev-qa-db-ja.com

端末を閉じても存続するコマンドを実行するにはどうすればよいですか?

時々私はプロセスを始めてそれを忘れたいです。コマンドラインから起動すると、次のようになります。

redshift

ターミナルを閉じることができない、またはプロセスを強制終了します。プロセスを終了せずにターミナルを閉じることができるような方法でコマンドを実行できますか?

339
Matthew

次の2つのいずれかが機能します。

$ Nohup redshift &

または

$ redshift &
$ disown

これがどのように機能するかの詳細については、以下を参照してください。

342
Steven D

プログラムがすでに実行中の場合は、Ctrl-Zを使用して一時停止し、bgを使用してバックグラウンドにプルしてから、次のようにdisownを使用できます。

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
147
Stefan

良い答えはすでに@StevenDによって投稿されていますが、これでもう少し明確になると思います。

端末の終了時にプロセスが強制終了される理由は、開始するプロセスが端末の子プロセスであるためです。ターミナルを閉じると、これらの子プロセスも強制終了されます。たとえば、Konsoleでkate &を実行すると、pstreeでプロセスツリーを確認できます。

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

kateを終了するときにkonsoleプロセスをkonsoleから切り離すには、次のようにコマンドでNohupを使用します。

Nohup kate &

konsoleを閉じると、pstreeは次のようになります。

init-+
     |-kate---2*[{kate}]

そしてkateは生き残ります。 :)

別の方法は、screen/tmux/byobuを使用することです。これにより、ターミナルに関係なく、シェルを実行し続けることができます。

50
gertvdijk

ターミナルでこのようなプロセスを実行できます

setsid process

これにより、プログラムが新しいセッションで実行されます。説明通り http://hanoo.org/index.php?article=run-program-in-new-session-linux

31
hanoo

提案はすべてうまくいきますが、私の代替案は、画面に仮想端末をセットアップするプログラムであるscreenを使用することです。

screen -S session_nameで始めることを検討してください。 Screenは、事実上すべてのLinuxおよびUnix派生物にインストールできます。ヒッティング Ctrl+A と(小文字) C 2番目のセッションを開始します。これを押すと、最初のセッションを前後に切り替えることができます Ctrl+A そして  またはを押すことにより、新しいセッション Ctrl+A そして 1。 1つのターミナルで最大10のセッションを持つことができます。私は以前、職場でセッションを開始し、家に帰って、職場のマシンにsshしてから、screen -d -R session_nameを呼び出していました。これにより、そのリモートセッションに再接続されます。

10
apolinsky

私は好む:

(アプリケーション名と)

例:linux@linux-desktop:~$ (chromium-browser &)

コマンドを入力するときは、必ず括弧を使用してください!

8
daGo

私にはスクリプトがあります:

  • バックグラウンドで任意のコマンドを実行する

  • ターミナルウィンドウでそれらが殺されるのを止めます

  • 出力を抑制します

  • 終了ステータスを処理します

私は主にgeditevinceinkscapeなどに使用します。これらはすべて、多くの迷惑な端末出力を持っています。コマンドがTIMEOUTの前に終了すると、Nohupの終了ステータスがゼロではなく返されます。

#!/bin/bash

TIMEOUT=0.1

#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
Nohup "${@}" >/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 ${@}"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS

例...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
7
jozxyqk

これをすべて行うシェルのみの方法は、標準入力を閉じてコマンドのバックグラウンドを設定することです。

command <&- & 

その後、シェルを終了しても終了しません。 stdoutのリダイレクトは、すてきなオプションです。

不利な点は、事後にこれを行うことができないことです。

7
w00t

ログアウトしてターミナルセッションを閉じたときにHUP信号を受信しないようにプロセス(PID)を設定できます。次のコマンドを使用します。

Nohup -p PID
4
tony

間違いなく apolinskyが提供する回答 と似ていますが、screenのバリアントを使用しています。バニラコマンドはこんな感じ

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

セッションは次の方法で切断できます Ctrl ACtrl D screen -rを使用して単純なケースで再接続しました。これをsessionにあるPATHというスクリプトにラップして、便利なアクセスの準備ができました。

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

これは、事前にプログラムを切断したい場合にのみ機能します。 すでに実行されているプログラムを切断することはできません。

3
roaima

以前に投稿された他の回答と同様に、実行中のプロセスを転送して reptyr を使用して「画面」を遡及的に使用し、ターミナルを閉じることができます。手順はこの post で説明されています。実行する手順は次のとおりです。

  1. プロセスを一時停止します
  2. バックグラウンドでプロセスを再開します
  3. プロセスを否認する
  4. スクリーンセッションを起動する
  5. プロセスのPIDを見つける
  6. Reptyrを使用してプロセスを引き継ぐ
2
user308879