web-dev-qa-db-ja.com

別のユーザーとしてスクリプトを開始する

/etc/init.d/にスクリプトを作成しました。このスクリプトは、他の(root特権を持たない)ユーザーがホームディレクトリから起動したかのように、他のいくつかのスクリプトを実行する必要があります。

これらのスクリプトは次のように起動します:Sudo -b -u <username> <script_of_a_particular_user>

そしてそれは機能します。しかし、実行を継続するすべてのユーザースクリプト(たとえば、一部のウォッチドッグ)については、対応する親Sudoプロセスがまだアクティブでrootとして実行されているのがわかります。これにより、アクティブプロセスリストに混乱が生じます。

だから私の質問は:どうすれば既存のbashスクリプトから別のスクリプトを別のユーザーとして起動(フォーク)し、孤立した(スタンドアロン)プロセスとして残すことができますか?

詳細説明:
私は基本的に、.startUpと.shutDownという名前のホームディレクトリにあるそれぞれのサブディレクトリにある実行可能ファイルを実行して、システム起動時またはシステムシャットダウン時に実行する手段をマシンの他のユーザーに提供しようとしています。他の方法が見つからなかったので、それを正確に実行するbashスクリプトを記述し、それをサービススクリプトとして(スケルトンの例に従って)/etc/init.d/に構成しました。 start引数を指定すると、.startUpディレクトリからすべてが起動され、stop引数を指定して実行すると、すべてのユーザーの.shutDownディレクトリからすべてが起動されます。

あるいは、この問題を解決するために既存の解決策を使用できたかどうかにも興味があります。

[〜#〜]更新[〜#〜]
少し調べてみたところ、次の質問が見つかりました: https://unix.stackexchange.com/questions/22478/detach-a-daemon-using-Sudo

そこに受け入れられた答え、使用する:Sudo -u user sh -c "daemon & disown %1"、私のために働く。しかし、私もdisown%1なしで試しましたが、同じです。だから、これは私が期待したとおりに機能するものです:

Sudo -u <username> bash -c "<script_of_a_particular_user> &"

私の追加の質問は今、なぜそれが否認なしで機能するのですか?いくつかの潜在的な特別なケースのために、私はまだdisownコールを残すべきですか?

更新2

どうやらこれも動作します:

su <username> -c "<script_of_a_particular_user> &"

この呼び出しとSudo呼び出しの間に違いはありますか?これはまったく別の問題である可能性があることを知っています。しかし、私がここで答えを見つけているので、おそらくこのトピックのために、誰かがここでこれを明確にできるでしょう。

更新3
suまたはSudoを使用するこれらのメソッドは両方とも、起動後に新しいstartparプロセス(rootとして実行される単一プロセス)を生成します機械。プロセスリストに次のように表示されます:

startpar -f -- <name_of_my_init.d_script>

なぜこのプロセスが生成されるのですか?他のinit.dスクリプトでこのプロセスが実行されていないため、明らかに私は何か間違っています。

UPDATE 4
startparの問題が解決されました。そのために別の質問を始めました:
rc.localまたはinit.dからプロセスを開始すると、startparプロセスがハングしたままになる

そして、非特権ユーザーのための起動メカニズムをさらに議論する別の質問:
初期化とシャットダウンの自動実行機能を通常のユーザー(非root)に提供します

12
Ivan Kovacevic

これに対する正しい答えは、適切な「デーモン化」のために、標準入力、標準出力、および標準エラーを/ dev/null(または実際のファイル)にリダイレクトする必要があるということでした。

su someuser -c "Nohup some_script.sh >/dev/null 2>&1 &"

su-ユーザーIDをsomeuserに置き換えます
-c-指定されたコマンドを実行するためのsu引数
Nohup-ハングアップの影響を受けないコマンドを実行します。親プロセスが子プロセスを終了する場合を防ぐため。念のためここに追加しました。しかし、実際には私の特定のケースでは効果がありません。必要かどうかは環境によって異なります(checkshopt
>/dev/null-標準出力を何にもリダイレクトせず、基本的に無効にします。
2>&1-標準エラー(2)出力を標準出力(1)にリダイレクトし、nullにリダイレクトします
-バックグラウンドにデタッチします。これにより、標準入力も/ dev/nullにリダイレクトされます。

これは本質的に、Debian dpkgのstart-stop-daemonユーティリティがコアで行うこととまったく同じです。そのため、コードに別の外部ユーティリティコールを導入するよりも、この方法でスクリプトを開始する方を好みます。 start-stop-daemonは、起動する必要がある本格的なデーモンプログラムがあり、その後に追加の機能が必要な場合start-stop-daemonが提供します(たとえば、指定されたプロセスがすでに実行されているかどうかをチェックして、再度起動しないようにします)。

また、プロセスのファイル記述子を/ dev/nullにリダイレクトする代わりに閉じることもできます。次に例を示します。

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"

0 <&-標準入力を閉じる(0)
1>&-標準出力を閉じます(1)
2>&-標準エラー(2)の出力を閉じます

長いファイル記述子番号が指定されているため、<>記号の方向は重要ではありません。だからこれも同じように良いです:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"

または

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"

ただし、stdinとstdoutの番号なしで、方向が重要な場合、それを書くには少し短い方法があります。

su someuser -c "some_script.sh <&- >&- 2>&- &" 

ファイル記述子が閉じているか、/ dev/nullにリダイレクトされている場合(start-stop-daemonが/ dev/nullへのリダイレクトを行っている)プロセスデーモンとしてバックグラウンドで実行しても安全です。したがって、起動時にスクリプトを起動する際の問題(startpar)を回避するために必要なことです。

私は最初のアイデアからソリューション全体を実装し、GitHubに配置しました:
https://github.com/ivankovacevic/userspaceServices

18
Ivan Kovacevic

--userオプションを指定して、init.dから start-stop-daemon を使用できます。

3
dmourati

私はこれを完全にテストしていませんが、次のようなものだと思います:

/sbin/start-stop-daemon --background --start --exec /home/USER/.startUp --user USER --pidfile=/home/USER/.startUp.pid --make-pidfile

起動時とその後

/sbin/start-stop-daemon --stop --user USER --pidfile=/home/USER/.startUp.pid

シャットダウンするとき。

.shutDownスクリプトの処理は、スタートアップのようなもので実行できますが、シャットダウンはとにかく発生するはずなので、スクリプトが最後まで実行されるとは確信できません:-)

トリックを実行する必要があります。おそらくいくつかの入力リダイレクトをスローする必要がありますが、ログファイルがいっぱいになることを心配する必要があります。

2
Mr Shark

suを使ってみましたか?

su -c /home/user/.startUp/executable - user

-cはsuにコマンドを実行するよう指示し、最後のパラメーターはそれを実行するユーザーです。

1
Tero Kilkanen