web-dev-qa-db-ja.com

Linuxサービスを別のユーザーとして実行するためのベストプラクティス

サービスはデフォルトで、RHELボックスでの起動時にrootとして開始します。正しく思い出せば、/etc/init.dのinitスクリプトを使用する他のLinuxディストリビューションでも同じことが言えます。

代わりに、プロセスを選択した(静的な)ユーザーとして実行する最良の方法は何だと思いますか?

私が着いた唯一の方法は、次のようなものを使用することでした:

 su my_user -c 'daemon my_cmd &>/dev/null &'

しかし、これは少しだらしないようです...

他の非rootユーザーとして自動的にサービスを開始する簡単なメカニズムを提供する魔法が少し隠れていますか?

EDIT:このインスタンスで開始するプロセスは、PythonスクリプトまたはJavaプログラム。私はむしろそれらの周りにネイティブラッパーを書きたくないので、残念ながら Black が示唆するように setuid() を呼び出すことができません。

135
James Brady

Debianでは、start-stop-daemonユーティリティを使用します。このユーティリティは、pidファイルを処理し、ユーザーを変更し、デーモンをバックグラウンドに入れます。

私はRedHatに精通していませんが、すでに使用しているdaemonユーティリティ(/etc/init.d/functions、btwで定義されています)は、start-stop-daemonと同等のものとしてどこでも言及されているため、プログラムのuidを変更することもできます。あなたのやり方はすでに正しいものです。

ネットを見ると、使用できる既製のラッパーがいくつかあります。すでにRedHatにパッケージ化されているものもあります。 daemonize などをご覧ください。

67
user3850

ここですべての提案を確認した後、私は自分の立場にある他の人に役立つと思ういくつかのことを発見しました:

  1. hop/etc/init.d/functionsを指すのに正しい:daemon関数は既に代替ユーザーを設定することを許可している:

    daemon --user=my_user my_cmd &>/dev/null &
    

    これは、プロセス呼び出しをrunuserでラップすることで実装されます-これについては後で詳しく説明します。

  2. Jonathan Leffler は正しい:Pythonにはsetuidがあります:

    import os
    os.setuid(501) # UID of my_user is 501
    

    ただし、JVM内からsetuidできるとはまだ思いません。

  3. surunuserのどちらも、既存のユーザーとしてコマンドを実行するように要求するケースを適切に処理しません。例えば。:

    [my_user@my_Host]$ id
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    [my_user@my_Host]$ su my_user -c "id"
    Password: # don't want to be prompted!
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    

surunuserの動作を回避するために、initスクリプトを次のようなものに変更しました。

if [[ "$USER" == "my_user" ]]
then
    daemon my_cmd &>/dev/null &
else
    daemon --user=my_user my_cmd &>/dev/null &
fi

ご協力ありがとうございます!

53
James Brady
  • 一部のデーモン(Apacheなど)は、 setuid()
  • setuid-file flag を使用して、別のユーザーとしてプロセスを実行できます。
  • もちろん、あなたが言及した解決策も同様に機能します。

独自のデーモンを作成する場合は、setuid()を呼び出すことをお勧めします。このようにして、あなたのプロセスは

  1. ルート権限を使用します(ログファイルを開く、pidファイルを作成するなど)。
  2. 起動中の特定の時点でルート権限を削除します。
5
Black

他に注意することを追加するだけです:

  • Init.dスクリプトのsudoはttyを必要とするため、良くありません(「Sudo:すみません、Sudoを実行するにはttyが必要です」)
  • Javaアプリケーションをデーモン化する場合は、Java Service Wrapper(ユーザーIDを設定するメカニズムを提供する)を検討することをお勧めします。
  • 別の選択肢はsu --session-command = [cmd] [user]
3
pdeschen

svnサーバー用のCENTOS(Red Hat)仮想マシン:/etc/init.d/svnserverを編集して、pidをsvnが書き込み可能なものに変更します。

pidfile=${PIDFILE-/home/svn/run/svnserve.pid}

オプション--user=svnを追加しました:

daemon --pidfile=${pidfile} --user=svn $exec $args

元のpidfileは/var/run/svnserve.pidでした。デーモンは、becaseuを起動せず、rootのみがそこに書き込むことができました。

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart
3
dulcana

注意するべきいくつかの事柄:

  • 既に述べたように、suが既にターゲットユーザーである場合、パスワードを要求します。
  • 同様に、setuid(2)は、すでにターゲットユーザー(一部のOS)である場合に失敗します
  • setuid(2)は、/ etc/limits.conf(Linux)または/ etc/user_attr(Solaris)で定義された特権またはリソース制御をインストールしません
  • Setgid(2)/ setuid(2)ルートに行く場合は、initgroups(3)を呼び出すことを忘れないでください-これについての詳細 here

通常、デーモンを起動する前に/ sbin/suを使用して適切なユーザーに切り替えます。

2
claymation

Initスクリプトで次のことを試してみてください。

setuid $USER application_name

それは私のために働いた。

2
cyberJar

Spring .jarアプリケーションをサービスとして実行する必要があり、これを特定のユーザーとして実行する簡単な方法を見つけました。

Jarファイルの所有者とグループを、実行したいユーザーに変更しました。次に、init.dでこのjarをシンボリックリンクし、サービスを開始しました。

そう:

#chown myuser:myuser /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar

#ln -s /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar /etc/init.d/springApp

#service springApp start

#ps aux | grep Java
myuser    9970  5.0  9.9 4071348 386132 ?      Sl   09:38   0:21 /bin/Java -Dsun.misc.URLClassPath.disableJarChecking=true -jar /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar
0
Somaiah Kumbera