web-dev-qa-db-ja.com

Bashでリダイレクトを使用してSudoを使用するときに「許可が拒否されました」を解決する方法は?

Sudoを使用してファイルの編集を許可すると、定期的に「許可が拒否されました」と表示されます。

たとえば、私のマウスは不安定で動作が遅いので、ポーリングを無効にしたいと思います。

Sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

パスワードの入力を求められますが、次に取得します:

bash: /etc/modprobe.d/local.conf: Permission denied

そこで、以下を使用して、ポーリングを無効にする一時的な変更を試みました。

Sudo echo N> /sys/module/drm_kms_helper/parameters/poll

さらに、システムは次のように応答しました。

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

何か案は?

135
Jack

出力のリダイレクト(>演算子による)は、echoではなく、シェルによって行われます。ルートとしてログインする必要があります

Sudo -i

次に、リダイレクトを使用できます

echo N> /sys/module/drm_kms_helper/parameters/poll

それ以外の場合は、Sudoでbash文字列を実行できます

Sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
153
shantanu

出力のリダイレクトはシェルによって行われますコマンドの呼び出し元。だから、すべてをビットに分割し、ここで何が起こっているのか*:

  • シェルはSudo echo "options drm_kms_helper poll=N"を呼び出し、echo "options drm_kms_helper poll=N"コマンドラインでSudoコマンドを実行します

  • Sudoはパスワードを要求し、スーパーユーザーシェルを開いてecho "options drm_kms_helper poll=N"を呼び出します。これはechoコマンドを実行して"options drm_kms_helper poll=N"を渡します

  • echoは、root特権で実行され、文字列を標準出力に出力します。

  • echoコマンドは終了、スーパーユーザーシェルは終了、Sudoは終了

  • コマンドが呼び出されたシェルは出力を収集し、それを/etc/modprobe.d/local.confにリダイレクトしようとします。これは、rootのみが書き込み可能です。 「許可が拒否されました」エラーが発生します。

これを修正する方法については、@ shantanuの回答を参照してください。


(*)-上記のシーケンスはコマンドが失敗する理由を理解するのに役立ちますが、実際には多少の順序が乱れます:元のシェルはリダイレクトを認識し、Sudo ...コマンドを呼び出す前に書き込み用にファイルを開こうとします。ファイルのオープンに失敗すると、シェルはファイルに書き込むはずのコマンドを呼び出しさえしません(これを指摘してくれた@PanosRontogiannisに感謝します)。

簡単なテストを次に示します。

$ touch ./onlyroot.txt
$ Sudo chown root:root ./onlyroot.txt
$ Sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

上記のテストでは、whoami | tee who.txtwho.txtという名前のファイルを作成し、「root」という単語を含みます。ただし、呼び出し元のシェルで出力のリダイレクトが失敗すると、コマンドが呼び出されなかったため、「who.txt」ファイルも失われます。

74
Sergey

Shantanuの答えに追加:

...または、次のような tee コマンドを使用できます。

Sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

または、コマンドの出力の場合:

echo 10 | Sudo tee /sys/module/drm_kms_helper/parameters/poll
60
Untitled

ここで言及したことのないアプローチは、単にコマンドライン全体を独自のシェルで実行することです。 Sudoマンページ自体は、このアプローチの例を示しています。

/ homeパーティション内のディレクトリの使用リストを作成します。これにより、サブシェルでコマンドが実行され、cdおよびファイルリダイレクトが機能することに注意してください。

$ Sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
15
kojiro

別のオプションは、一時ファイルを使用することです。これは、bashスクリプトで役立ちます。

temp=$(mktemp)
echo "Hello, world!" > $temp
Sudo cp $temp /etc/wherever
4
user545424

Sudo dd of=

必要に応じて追加するには:

echo inbytes | Sudo dd of=outfile oflag=append conv=notrunc

または、ファイルを最初から再作成するには:

echo inbytes | Sudo dd of=outfile

利点:

  • /dev/nullリダイレクトがないため、teeよりも優れています
  • shより良い
  • ddには多くの強力なオプションがあります。 status=progressは転送の進行状況を確認します

Sudoがコマンドにstdinを転送するため、機能します。