私はUbuntuのTilda(ドロップダウンターミナル)を私の「コマンドの中心」として使っています - 他の人がGNOME Do、Quicksilver、Launchyを使うのと同じ方法です。
しかし、私はそれが起動されている端末からプロセス(例えばFirefox)を完全にデタッチする方法に苦労しています - すなわちそのような(非)子プロセスを防ぐ
たとえば、 "適切な"ターミナルウィンドウでVimを起動するために、私は次のような簡単なスクリプトを試しました。
exec gnome-terminal -e "vim $@" &> /dev/null &
ただし、それでも汚染の原因となります(ファイル名を渡してもうまくいかないようです)。
まず第一に;プロセスを開始したら、最初に停止してバックグラウンド設定することができます(ヒット Ctrl - Z)と入力して、バックグラウンドで再開するためにbg
を入力します。これは「ジョブ」になり、stdout
/stderr
/stdin
はまだ端末に接続されています。
プロセスの最後に「&」を追加することで、すぐにバックグラウンドとしてプロセスを開始できます。
firefox &
沈黙させてバックグラウンドで実行するには、これを使用します。
firefox </dev/null &>/dev/null &
いくつかの追加情報:
Nohup
は、標準のstdout/stderrを代わりにファイルに送ることができ、親スクリプトを閉じても子が見えなくなるように、アプリケーションを実行するためにを使用できるプログラムです。ただし、アプリケーションを起動する前にそれを使用するための先見の明がある必要があります。 Nohup
が機能する方法のため、実行中のプロセスにそれを適用することはできません。
disown
はシェルのジョブリストからシェルジョブを削除するbash組み込みです。これが基本的に何を意味するのかというと、fg
やbg
をそれ以上使用することはできないということですが、もっと重要なことは、シェルを閉じてもハングアップしたりSIGHUP
をその子に送ったりしないということです。 Nohup
とは異なり、disown
が使用されます。後プロセスが起動され、バックグラウンドになりました。
あなたができないのは、起動後にプロセスの標準出力/標準エラー/標準入力を変更することです。少なくともシェルからではありません。あなたが自分のプロセスを起動し、その標準出力があなたの端末であると言うなら(これはあなたがデフォルトで行うことです)、そのプロセスはあなたの端末に出力するように設定されます。あなたのShellはプロセスのFD設定とは関係がありません。それは純粋にプロセス自体が管理するものです。プロセス自体がその標準出力/標準エラー出力/標準終了を閉じるかどうかを決めることができますが、シェルで強制的に閉じることはできません。
バックグラウンドプロセスの出力を管理するために、スクリプトからたくさんのオプションがあります。おそらく "Nohup"が最初に思い浮かぶでしょう。しかし対話型プロセスの場合は、開始しても沈黙を忘れています(firefox < /dev/null &>/dev/null &
)ことはできません。
GNU screen
を取得することをお勧めします。 screenを使うと、プロセスの出力が邪魔になって新しいシェル(^Ac
)を開くときに実行中のシェルを閉じることができます。
おお、そしてところで、あなたがそれを使っているところで "$@
"を使わないでください。
$@
は、$1
、$2
、$3
...を意味します。これにより、コマンドは次のようになります。
gnome-terminal -e "vim $1" "$2" "$3" ...
-eはone引数だけを取るので、おそらくそれはあなたが望むものではありません。スクリプトが1つの引数しか処理できないことを示すには、$1
を使用します。
gnome-terminal -e
は1つの引数(シェルコマンド文字列)のみを取るため、(-e
を使用して)与えたシナリオで複数の引数を正しく機能させることは本当に困難です。あなたはあなたの議論を一つにエンコードしなければならないでしょう。最善かつ最も堅牢な、しかしかなりまとまった方法は、次のとおりです。
gnome-terminal -e "vim $(printf "%q " "$@")"
Nohup cmd &
Nohup
プロセスを完全にデタッチ(デーモン化)
bash
を使用している場合は、disown [jobspec]
を試してください。 bash(1) を参照してください。
あなたが試すことができるもう一つのアプローチはat now
です。スーパーユーザーではない場合は、at
を使用する許可が制限されている可能性があります。
これらの答えを読んで、私はNohup <command> &
を出すことで十分であるという最初の印象の下にありました。 gnome-terminalでzshを実行しても、Nohup <command> &
はシェルが終了時に子プロセスを強制終了するのを妨げないことがわかりました。 Nohup
は特に非対話型シェルでは便利ですが、子プロセスがSIGHUP
シグナルのハンドラをリセットしない場合にのみ、この動作が保証されます。
私の場合、Nohup
はハングアップシグナルがアプリケーションに届かないようにするべきでしたが、子アプリケーション(この場合はVMWare Player)はSIGHUP
ハンドラをリセットしていました。その結果、端末エミュレータが終了しても、サブプロセスが終了する可能性があります。私の知る限りでは、プロセスがシェルのjobsテーブルから削除されていることを確認することによってのみ、これを解決できます。 Nohup
がShellの組み込み関数で上書きされる場合もありますが、そうでない場合はこれで十分な場合があります。
disown
は、bash
、zsh
、およびksh93
に組み込まれたシェルです。
<command> &
disown
または
<command> &; disown
あなたがワンライナーを好むならば。これには、ジョブテーブルからサブプロセスを削除するという一般的に望ましい効果があります。これにより、誤って子プロセスに何も通知せずにターミナルエミュレータを終了できます。 SIGHUP
ハンドラがどんな風に見えても、これはあなたの子プロセスを殺してはいけません。
表示されなくなった後も、プロセスはターミナルエミュレータの子です(実際にこれを見たい場合はpstree
で遊んでください)が、ターミナルエミュレータの終了後はinitプロセスにアタッチされているはずです。言い換えれば、すべてはそれがあるべき姿であり、あなたがおそらくそれがありたいことなのです。
あなたのシェルがdisown
をサポートしていない場合はどうしますか?私は強くすることを強く勧めますが、その選択肢がなければ、あなたにはいくつかの選択肢があります。
screen
とtmux
はこの問題を解決することができますが、それらははるかに重い解決策であり、私はそのような単純なタスクのためにそれらを実行しなければならないのが嫌いです。これらは、通常はリモートマシン上でttyを管理したい状況に非常に適しています。setopt Nohup
のような機能をサポートしているかどうかを見ることは望ましいかもしれません。これは、シェルの終了時にSIGHUP
をjobsテーブル内のジョブに送信しないように指定するために使用できます。シェルを終了する直前にこれを適用することも、常にオンにしたい場合は~/.zshrc
などのシェル構成に追加することもできます。tcsh
やcsh
でこれを行う方法を見つけることができませんでしたが、これはやや厄介です。exec()
とする小さなCプログラムを書いてください。これは非常に貧弱な解決策ですが、ソースは数十行で構成されるべきです。そうすれば、Cプログラムにコマンドライン引数としてコマンドを渡すことができるため、jobsテーブルにプロセス固有のエントリを追加する必要がなくなります。Nohup $COMMAND &
$COMMAND & disown
setsid command
私は長い間2番を使ってきましたが、3番も同じように機能します。また、disown
には-h
のNohup
フラグがあり、-a
ですべてのプロセスを却下し、-ar
で実行中のすべてのプロセスを却下できます。
サイレンシングは$COMMAND &>/dev/null
によって行われます。
お役に立てれば!
tcsh(および他のシェルでも同様)では、括弧を使ってプロセスを切り離すことができます。
これを比較してください。
> jobs # shows nothing
> firefox &
> jobs
[1] + Running firefox
これに:
> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>
これは仕事のリストからFirefoxを削除しますが、それはまだ端末に結び付けられています。このノードに 'ssh'でログインした場合、ログアウトしようとしてもsshプロセスはハングします。
Screenがあなたの問題を解決するかもしれないと思う
Bashの最もシンプルで唯一の正しい答え:
command & disown
端末からではなくシェルからプロセスを切り離す必要はありません。
Ttyシェルの関連付けを解除するには、サブシェルからコマンドを実行します。
(コマンド)&
終了時に端末が閉じられましたが、プロセスはまだ生きています。
チェック -
(sleep 100) & exit
他の端末を開く
ps aux | grep sleep
プロセスはまだ生きています。
仕事のバックグラウンド化とフォアグラウンド化は、おそらくすべてのUnixシステム管理者が知るべき最初のことの1つです。
これがbashで行われる方法です:
./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
あなたは、Nohupコマンドを使ってあなたのコマンドを実行することができます、これはあなたのプロセスをデタッチし、与えられたファイルに出力をリダイレクトします...しかし、私はそれがまさにあなたが必要とするものではありません..
試す daemon - あなたのフレンドリーなパッケージマネージャから利用可能で、端末からそれ自身を分離するあらゆる方法を包括的に世話するべきです。
これをbashrc/zshrcに追加するだけです。
detach() {
"$@" 1>/dev/null 2>/dev/null &; disown
}
それから、あなたはこのような卑劣なコマンドを実行することができます。
detach gedit ~/.zshrc
私の.bashrcでは、私はまさにその目的のためにこれらの関数を持っています:
function run_disowned() {
"$@" & disown
}
function dos() {
# run_disowned and silenced
run_disowned "$@" 1>/dev/null 2>/dev/null
}
コマンドを端末から切り離して実行するには、コマンドの前にdos
を付けます。
この関数はbash
とzsh
で動作するように書かれています。
私はMac OS X上で、子プロセスが端末で破壊されないようにするために、Nohupとdisownの両方を使用する必要があることを発見しました。
これを行うには、次のスクリプトを使用します。コマンドが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
使用例
>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
Sudo apt install ucommon-utils
pdetach command
そこに行きます:)