スクリプト内からルート権限をリクエストする


23

sudo script.shまたはとして実行できるスクリプトがありますpkexec script.sh

スクリプトが名前で実行するときにユーザーにパスワードを要求した場合、ユーザーの観点からははるかに良いでしょうscript.sh

ルート特権でスクリプト全体にリクエストを「埋め込む」、pkexecまたはsudo実行するにはどうすればよいですか?

sudo sh -cスクリプトに関数があるため、すべてを実行することは最良の解決策ではないことに注意してください

回答:


55

これは動作します:

echo "$(whoami)"

[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

例:

./test.sh 
blade
[sudo] password for blade: 
root

3
これの良いところは、再帰ですexec-それ自体を呼び出しますが、同時にprocessを置き換えるため、スクリプトの複数のインスタンスを生成しません
Sergiy Kolodyazhnyy

1
救助への再帰!!! 数日中にこれに賞金を追加することを思い出してください!
ファビー

6
これを行うときに注意する必要があるのは、特権の昇格です。基本的に、ルートとして実行するコマンドが増えるほど、悪意のあるハッカーが何かを悪用してルートアカウントにアクセスする機会が増えます。スクリプト全体をルートとして実行することは常に間違っているとは言いませんが、実行する前に少し考えてみる価値があります。答えがそれに触れるならば、それは(必要ではないが)いいと思う。
デビッドZ

/ etc / sudoersに適切なタイムアウト値が設定されている場合、オプションで、rootアクセスが本当に必要なスクリプト内の各コマンドの前にsudoを配置できます。私がしばしば混乱することの1つは、sudoがパスワード入力のために/ dev / nullを取得して失敗するため、GUIからそのようなスクリプトを呼び出すことは機能しないことです。gksudoとkdesudoは、GUIを使用してパスワードを要求するため、処理するように設計されています。
ジョー

1
@ Coder256:あなたの編集が正しかったとは思わない。 "$@"パラメータごとに1つずつ、複数の単語に展開されます。
jwodder

12

きれいなダイアログが必要な場合は、このようなものを試してください。私が書いた他の何かからこれをまっすぐに抜き取ったので、あなたが必要としないかもしれない余分なものがありますが、それは一般的なアイデアを示しています:

brand="My Software"

# Check that the script is running as root. If not, then prompt for the sudo
# password and re-execute this script with sudo.
if [ "$(id -nu)" != "root" ]; then
    sudo -k
    pass=$(whiptail --backtitle "$brand Installer" --title "Authentication required" --passwordbox "Installing $brand requires administrative privilege. Please authenticate to begin the installation.\n\n[sudo] Password for user $USER:" 12 50 3>&2 2>&1 1>&3-)
    exec sudo -S -p '' "$0" "$@" <<< "$pass"
    exit 1
fi

sudoダイアログ

これは、まだ持っていない場合にインストールできるホイップテールを使用します。

sudo apt-get install whiptail

1
パスワードを変数に保存するのはなぜですか?
heemayl

10
電話しないでくださいexec echo [PASSWORD]すべてのユーザーが表示できるコマンドラインでパスワードを使用してプロセスを生成します。組み込みコマンドecho(組み込みバージョンをで強制するbuiltin echo)またはbashism <<<(次のようにsudo ... <<< "$pass")を使用します。Shおよびその他のシェルには、これらのケースのヒアドキュメントがあります。また、特殊文字が含まれている場合はパスワードを引用してください。
デビッドフォースター

または、whiptailコマンドを別のスクリプトに入れて、カスタムパスワードプロンプトSUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"sudo処理するなどの方法を使用します。
デビッドフォースター

@DavidFoersterこれで問題はありませんが、2つのスクリプトが必要になるか、askpassスクリプトを一時ファイルに書き込んでsudoに渡します。
マイケルハンプトン

ただし、変数にパスワードを渡すのは望ましくないことを既に指摘した人もいました。idのアプローチは、ダイアログの出力を名前付きパイプに渡すことです。askubuntu.com/ a / 704643/295286
Sergiy Kolodyazhnyy

11

blade19899の答えは確かに進むべき道ですがsudo bash、シバンを呼ぶこともできます。

#!/usr/bin/sudo bash
# ...

明らかな注意点は、これはスクリプトが呼び出された場合にのみ機能し、スクリプトが呼び出さ./scriptれた直後に失敗することbash scriptです。


5
これがbash script、スクリプトを呼び出すためにコマンドラインに入力するべきではない理由の1つです。スクリプトbash#!行内以外を指定している場合、withを呼び出すとbash script失敗します。また、bash script.pyそれを使用してpythonスクリプトを呼び出そうとしても失敗します。
カスペルド

1
perl scriptただし、で実行できます。Perlは、本当に素晴らしいことを目指して、shebang行をチェックし、perlを呼び出していない場合は正しいプログラムを実行します。
tbodt

sudoを使用してスクリプト内のすべてのコマンドを実行しているため、これは悪いことです。本当にsudoを必要とするいくつかのコマンドを分離し、必要に応じて追加することをお勧めします。これらのsudo呼び出しに関数の評価を含めないでください。それらは可能な限り明確で最小限でなければなりません。
ダグラス

@DouglasHeld私はそれに同意するかもしれませんが、これは質問です:「どうすればroot権限でスクリプト全体を実行するためにpkexecまたはsudoにリクエストを「埋め込む」ことができますか?」これを実行できると便利な使用例があるはずです。
コス

6

ルートアクセスが必要なスクリプト内のコマンドの前書きsudo-ユーザーがまだアクセス許可を取得していない場合、スクリプトはその時点でパスワードの入力を求めます。

#!/bin/sh 
mem=$(free  | awk '/Mem:/ {print $4}')
swap=$(free | awk '/Swap:/ {print $3}')

if [ $mem -lt $swap ]; then
    echo "ERROR: not enough RAM to write swap back, nothing done" >&2
    exit 1
fi

sudo swapoff -a && 
sudo swapon -a

このスクリプトは、sudo <scriptname>またはとして実行できます<scriptname>。どちらの場合でも、パスワードの入力は1回だけ要求されます。


2
ここでの問題は、ルートアクセスを必要とする複数のコマンドが存在する可能性があることです。つまりsudo、25の異なるコマンドを冗長に呼び出す必要があります。sudoを1回呼び出す方が簡単です。ただし、ここでスクリプトがsudoを1回だけ呼び出すのは、sudoのタイムアウトが15分であるためです。それよりも時間がかかるコマンドは再プロンプトが必要になります。あなたのやり方はうまくいきます。。。動作に必要な方法ではありません。
セルギーコロディアズニー

@Serg小さなスクリプトの場合、私が持っていた方法は迅速かつ簡単でした-私は本当にエレガントなプログラマーではありません!
チャールズグリーン

このページに投稿する最高のプログラマーです。sudoを使用する必要があります-必要な場合にのみ、非常に明確な結果が期待されます。
ダグラス開催

4

ここで明らかな懸念に対処した人は誰もいないようです。置くsudoあなたが配布していること、あなたのスクリプト内では、不正なユーザーの習慣を促進します。(「ユーザーの観点から」と言うので、あなたはそれを配布していると仮定しています。)

真実はのバンキングのセキュリティの原則に似ているアプリケーションやスクリプト使用でのガイドラインがあるということです:あなたを呼び出すと、彼らは「あなたの銀行から」呼び出していると言う誰かにあなたの個人情報を与えることはありませんが、そしてそれは存在します同様の理由で。

アプリケーションのルールは次のとおりです。

プロンプトが表示されたら、パスワードを入力しないでください 何が行われているのか確信 これは、sudoアクセス権を持つすべてのユーザーに3回適用されます。

sudoコマンドラインで実行したためにパスワードを入力している場合は、すばらしいです。SSHコマンドを実行したために入力する場合は、問題ありません。もちろん、コンピューターにログインするときに入力する場合は、すばらしいです。

外部のスクリプトまたは実行可能ファイルを実行し、プロンプトが表示されたときにパスワードをうまく入力した場合、 、スクリプトがそれで何ません。ご存知のように、それをプレーンテキストの一時ファイルに保存することもできますし、それ自体のクリーンアップに失敗することさえあります。

明らかに未知のコマンドセットを実行することに関する別々の追加の懸念がありますrootが、私がここで話しているのはパスワード自体のセキュリティ維持することです。アプリケーション/スクリプトが悪意のあるものではないとしても、パスワードを安全に処理して防ぐ必要があります他のアプリケーションがそれを入手して悪意を持って使用。

したがって、これに対する私自身の個人的な反応は、ルート特権が必要な場合にスクリプトに入れる最良のことです:

#!/bin/bash
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

# do privileged stuff, etc.

私はあなたに完全に同意しますが、それが何をするのかを知らずに何かを実行するユーザーsudo script_nameは同じように脆弱ですが、それは同じです。たぶん、この考えは悪い習慣を助長するでしょう-私はそれについて何も言いません。しかし、キーはプログラムが何をするかを知ることであり、それはユーザーの責任です。これが、オープンソースソフトウェアの背後にある全体的なアイデアです。私自身のスクリプトについては、まあ。。。スクリプトはプレーンテキストです-ユーザーは、スクリプトが何をするかを知りたい場合に読むことができます
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyyも似ていますが、パスワードをスクリプトに直接入力した場合、実際はさらに悪化します。sudoで実行されるスクリプトは、まだパスワードを認識しません。
ワイルドカード

1

私はこのようにしました:

echo -n "Enter password for sudo rights: "
read -s pass

echo $pass | sudo -S [your command here]

4
少なくとも変数を引用してください。
ムル

また、パスワードがハイフンで始まる場合、変数を引用しても役に立たない場合があります。
ワイルドカード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.