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


138

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

何か案は?

回答:


157

>オペレーターを介した)出力リダイレクトは、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"

1
sudoでechoを実行できませんか?私が得た結果はどうsaji@laptop:~$ sudo echo "Hi" [sudo] password for saji: Hi
ですか

ファイルに書き込み、「何か」をエコーする>なんとかする。パイプを使用しています。それが問題です。
シャンタヌ

4
わかりました。その場合は、答えを更新して、実行中のエコーがその場合のみ問題であることを反映してください。
saji89

以下のechoようなことをしない限り、単に組み込みのシェルをsudoとして実行することはできませんsudo bash -c 'echo …'。ただし、POSIXシステムは通常、OS X echoなどの外部コマンドを提供し、/bin/echosudoはリガマロールなしで実行できます。したがって、echo通常実行するechoコマンドとsudoを使用して実行するコマンドは、おそらく2つの異なるが、類似したコマンドです。
小次郎

その場合、なぜこの質問への回答がエコーを示唆したのですか?askubuntu.com/questions/840431/...
ハルシャ

75

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

  • shell invokes sudo echo "options drm_kms_helper poll=N"、コマンドラインsudoecho "options drm_kms_helper poll=N"コマンドを実行します

  • sudoはパスワードを要求し、スーパーユーザーシェルを開きecho "options drm_kms_helper poll=N"、それを呼び出すechoコマンドを実行するを呼び出します"options drm_kms_helper poll=N"

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

  • echoコマンドは終了し、スーパーユーザーシェルは終了し、sudo終了します

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

これを修正する方法については、@ 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」ファイルも失われます。


シェルはsudoを「実行」する前に、シェル自体を「フォーク」し、/ etc / modprobe.d / local.confを開こうとする可能性が高いです。
Panos Rontogiannis

1
@PanosRontogiannis:ありがとう、答えを更新しました
セルゲイ

60

Shantanuの答えに追加:

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

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

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

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll

3
ルートとして+1ログインするのは、手作業にとって悪い考えであり、スクリプト化されたタスクにとっては非常に悪い考えです。
l0b0

2
また、同様sudo tee /sys/module/drm_kms_helper/parameters/poll > /dev/nullに印刷したくない場合stdout
ファビアンタンプ

16

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

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

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

ありがとう シンプルなソリューション
復元力

4

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

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

3

sudo dd of=

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

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

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

echo inbytes | sudo dd of=outfile

利点:

  • リダイレクトしteeないためよりも良い/dev/null
  • sh明示的なサブシェルがないためよりも優れています(ただし、リダイレクト用の暗黙的なサブシェル)
  • ddstatus=progress転送の進行状況を確認するなど、多くの強力なオプションがあります

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


1
これはいい。私ddたちはかつて偉大なファイルシステムを上書きする方法と考えていますが、それが日常的なタスクのためであることを理解していない-そして、ルートとしての他のコマンドも間違ったファイル/デバイスで使用すると大きな害を引き起こすことを理解しています。同様にsudo teesudo ddもちろんここの文字列でも動作しますsudo dd of=outfile <<<'hello world'。[編集してくれてありがとう。NBはsh -c 'cmd'sh本当に意味で除き、サブシェルではないシェルですが、サブプロセスである、すべての外部コマンドを1として開始]。
Eliahケーガン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.