私はさまざまなことを行うスクリプトを持っていますが、そのほとんどは特別な特権を必要としません。ただし、関数内に含まれている特定のセクションには、root権限が必要です。
スクリプト全体をrootとして実行する必要はなく、スクリプト内からroot権限でこの関数を呼び出すことができます。とにかくほとんどインタラクティブなので、必要に応じてパスワードを要求することは問題ではありません。しかし、Sudo functionx
を使用しようとすると、次のようになります。
Sudo: functionx: command not found
予想通り、export
は違いをもたらしませんでした。いくつかの理由により、関数を分割して別のスクリプトとして実行するのではなく、スクリプト内で直接関数を実行できるようにしたいと考えています。
関数を抽出して適切なディレクトリを見つけ、それをスタンドアロンスクリプトとして実行せずに、関数をSudoに「可視」にする方法はありますか?
この関数はページ自体が長く、複数の文字列が含まれています。また、メインスクリプトの他の場所で定義されているメニュー関数にも依存しています。
パスワードを変更することの1つであるため、Sudo ANYを持つ誰かが関数を実行できることを期待します。
これを行う簡単で直感的な方法はないことを認めます。これは少し厄介です。しかし、あなたはこのようにそれを行うことができます:
_function hello()
{
echo "Hello!"
}
# Test that it works.
hello
FUNC=$(declare -f hello)
Sudo bash -c "$FUNC; hello"
_
またはもっと簡単に:
_Sudo bash -c "$(declare -f hello); hello"
_
わたしにはできる:
_$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-Apple-darwin14.5.0)
$ hello
Hello!
$
$ FUNC=$(declare -f hello)
$ Sudo bash -c "$FUNC; hello"
Hello!
_
基本的に、_declare -f
_は関数の内容を返し、_bash -c
_にインラインで渡します。
すべての関数をbashの外部インスタンスからエクスポートする場合は、FUNC=$(declare -f hello)
をFUNC=$(declare -f)
に変更します。
編集
引用に関するコメントに対処するには、次の例を参照してください。
_$ hello()
> {
> echo "This 'is a' test."
> }
$ declare -f hello
hello ()
{
echo "This 'is a' test."
}
$ FUNC=$(declare -f hello)
$ Sudo bash -c "$FUNC; hello"
Password:
This 'is a' test.
_
「問題」とは、Sudo
が環境をクリアし(許可された少数の変数を除く)、セキュリティリスクから保護するために、いくつかの変数を事前定義された安全な値に設定することです。つまり、これは実際には問題ではありません。それが特徴です。
たとえば、PATH="/path/to/myevildirectory:$PATH"
を設定し、Sudo
がPATHを事前定義された値に設定しなかった場合、実行するすべてのコマンド(つまり、ほとんどのスクリプト)への完全パス名を指定しなかったスクリプト他のディレクトリの前に/path/to/myevildirectory
を探します。 ls
やgrep
のようなコマンド、またはその他の一般的なツールをそこに置くと、システムで好きなことを簡単に実行できます。
最も簡単で最善の方法は、関数をスクリプトとして書き直してパスのどこかに保存する(またはSudo
コマンドラインでスクリプトへのフルパスを指定する)です。これはとにかく行う必要があります。 Sudo
がrootとして任意のコマンドを実行できるように構成されていない限り)、chmod +x /path/to/scriptname.sh
で実行可能にします
シェル関数をスクリプトとして書き換えるのは、関数定義内のコマンドをファイルに保存するのと同じくらい簡単です(function ...
、{
、}
行なしで)。
私はそれを行うために自分のSudo
bash関数を書きました、それは関数とエイリアスを呼び出すように機能します:
function Sudo {
local firstArg=$1
if [ $(type -t $firstArg) = function ]
then
shift && command Sudo bash -c "$(declare -f $firstArg);$firstArg $*"
Elif [ $(type -t $firstArg) = alias ]
then
alias Sudo='\Sudo '
eval "Sudo $@"
else
command Sudo "$@"
fi
}
関数とエイリアスを組み合わせることができます
例:
function hello_fn() {
echo "Hello!"
}
alias hello='bash -c "$(declare -f hello_fn); hello_fn"'
alias Sudo='Sudo '
次にSudo hello
機能
Will's answer のバリエーションを以下に示します。追加のcat
プロセスが必要ですが、ヒアドキュメントの快適さを提供します。一言で言えば、それはこのようになります:
f ()
{
echo ok;
}
cat <<EOS | Sudo bash
$(declare -f f)
f
EOS
あなたがより多くの食べ物を考えたいなら、これを試してください:
#!/bin/bash
f ()
{
x="a b";
menu "$x";
y="difficult thing";
echo "a $y to parse";
}
menu ()
{
[ "$1" == "a b" ] &&
echo "here's the menu";
}
cat <<EOS | Sudo bash
$(declare -f f)
$(declare -f menu)
f
EOS
出力は次のとおりです。
here's the menu
a difficult thing to pass
ここでは、「メインスクリプトの別の場所で定義されている」問題の関数に対応するmenu
関数があります。 「他の場所」は、Sudo
を要求する関数が実行されているこの段階でその定義がすでに読み取られていることを意味する場合、状況は類似しています。しかし、それはまだ読まれていないかもしれません。その定義をトリガーする別の関数があるかもしれません。この場合 declare -f menu
をより洗練されたものに置き換えるか、menu
関数がすでに宣言されている方法でスクリプト全体を修正する必要があります。
スクリプトが(a)自己完結型であるか、または(b)(ホームディレクトリの場所を覚えているのではなく)場所に基づいてコンポーネントを調達できると仮定すると、次のようなことができます。
$0
パス名をSudo
コマンドで使用し、スクリプトがチェックするオプションを渡して、パスワードの更新を呼び出します。 (./myscript
を実行するだけでなく)パスでスクリプトを見つけることに依存している限り、$0
で絶対パス名を取得する必要があります。Sudo
はスクリプトを実行するため、スクリプトで必要な関数にaccessが含まれています。uid
をチェックし、rootユーザーとして実行されたことを認識し、オプションを設定してパスワードを更新するように指示し、実行します。スクリプトはさまざまな理由で繰り返し発生する可能性があります。特権の変更もその1つです。