シェルスクリプトの「sudo su」がスクリプトの残りをルートとして実行しないのはなぜですか?


36

サンプルスクリプトは次のようになります。

#!/bin/bash
sudo su
ls /root

./test.sh通常のユーザーとして使用する場合、代わりにlsスーパーユーザーとして実行して終了し、ルートに切り替えます。ログアウトするls /rootと、通常のユーザーとして実行されます。

誰かがそれについてのメカニズムについて教えてもらえますか?


13
sudo su目が痛くなる。
ジェラーン

sudoを十分に知らないために使用されます。したがって、意図的に破損したパスワードによってrootが保護されているシステムでsuを実行する方法が必要です。ただし、yes sudoはsuの使用を「冗長化」します。
ヨハン

1
sudo -sただし、を使用することはできませんか?
ジョーZ.

@Johan、私sudo suはのオプションsuよりものオプションに慣れているため、よく使用しますsudo。私はsudoのオプションを十分に知っていますが、suのオプションをより速く入力できます。しかし、はい、それは私がsudoを十分に知らないことを意味すると思います。
user606723

1
sudoのmanページを確認しました。表示されますsudo -iに似ているsu -しばらくsudo -sのように動作su(ダッシュなし)
ヨハン

回答:


49

スクリプト内のコマンドは、個別に1つずつ実行されます。スクリプト内のすべてのコマンドの親としてのスクリプト自体は別の独立したプロセスであり、suコマンドはrootに変更できず、変更できません。suコマンドはroot特権で新しいプロセスを作成します。

そのsuコマンドが完了すると、同じユーザーとして実行されている親プロセスがスクリプトの残りを実行します。

あなたがしたいことは、ラッパースクリプトを書くことです。特権コマンドは、たとえば、メインスクリプトに入ります。~/main.sh

#!/bin/sh
ls /root

ラッパースクリプトは、次のようにルート権限でメインスクリプトを呼び出します

#!/bin/sh
su -c ~/main.sh root

このプロセスを起動するには、ラッパーを実行します。ラッパーは、ユーザーをルートユーザーに切り替えた後にメインスクリプトを起動します。

このラッパー手法を使用して、スクリプトをそれ自体のラッパーに変えることができます。基本的にルートとして実行されているかどうかを確認し、そうでない場合は「su」を使用して自分自身を再起動します。

$ 0はスクリプトに自分自身を参照させる便利な方法であり、whoamiコマンドは私たちが誰であるかを教えてくれます(rootですか?)

したがって、組み込みラッパーを備えたメインスクリプトは、

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

execの使用に注意してください。これは、「このプログラムを置き換える」ことを意味します。これは、実行を事実上終了し、suによって起動された新しいプログラムをrootで開始して、先頭から実行します。置換インスタンスは「ルート」であるため、||の右側は実行されません。


1
fwiw、この点の補遺。このようなスクリプトを作成している場合、$ EUIDをチェックするifステートメントを最初に実行し、ゼロでない場合はsudo自体を実行して終了し、そうでない場合はスクリプトの実行を続けます。
ブラッチリー

同意しました。これを説明するために回答を更新します。
ヨハン

2
おそらく少し古風ですが、私はすべての実行可能ファイルへの絶対パスが大好きなので、誰かが〜/ main.shスクリプトを不正なものに変更することはできません。スクリプトのUSER部分の攻撃
-artifex

2
また、* $への参照を含めることによって、それに渡された引数をキャッチすることができます
Bratchley

@JoelDavis私はいつも「引数にスペース文字があるとしたら」という壁にぶつかる。満足のいく解決策を見つけたことがありません。私はそれが必要なものは何でもと呼ばれ、その最後のスクリプトにして、元の引数を見つけるために、読み取るどのファイルの引数を渡され、その後、1行に1つの引数を一時ファイルに引数を出すスクリプトを書き、いったん。
ヨハン・

20

スクリプトで次を使用します。

sudo su <<HERE
ls /root
HERE

HEREブロック間のコードはルートとして実行されます。


6
sudo su2つのプログラムを呼び出しています。使用sudo -s <<HEREDOCまたはsu user <<HEREDOC...愚かな5分の制限。
ヨハン

6

さらに引数を指定しないsuと、rootのログインシェルが実行されます。これが、スクリプトの最初の行が実際に行うことです。終了すると、ログインシェルが閉じてsuが戻り、スクリプトの実行が継続されますls /root。つまり、2行目です。あなたは単にsudo ls /rootあなたがやりたいことをすることができると思います。


ええ、私はこれを行うことができることを知っていますlsが、これは単なるサンプルです。実際、ルート権限でもっと多くのことをする必要があります:-)だから、@ Ankitの答えを好みます。
Hongxu Chen

1

あなたが解雇したらsudo su効果的で新しいプロセスuserid (euid=EUID)フォークスーパーユーザーのを、それゆえ我々は、異なるプロセスIDで実行されている新しいbashを持って(pid=PID)同じ端末に関連します(tname=TTY)

説明

焼成後と仮定ps -A | grep bashあなたが持っている21460 pts/2 00:00:00 bash出力として。さて、あなたが実行したときに./test.sh両方のコマンドをsudo suls /rootにスプールされますPID 21460。実行後root、アクティブユーザーとしてps -A | grep bash再度ヒットすると、で実行されている新しいbashに気付くでしょうPID say, 21570。を終了するroot bashと、新しく分岐したbashが強制終了され、プロンプトがリリースされる前にuser's bashスプールされたコマンドが実行されls /rootます。


suまたはsudoの使用がbash(または他の場所)で「永続的」である場合、解決したよりも多くの問題が発生します。安全とセキュリティのために、ルートとして可能な限り最小限のことを行う必要があります。suとsudo(セキュリティ以外!)を持つ主なポイントは、root権限が必要なものについて慎重に考えるようにすることです。
ジョー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.