私は、開発中の RedHat Linux ボックスの 1 つで sudo アクセスを許可されており、通常は書き込みアクセスを持たない場所に出力をリダイレクトする必要があることがよくあるようです。
問題は、この不自然な例が機能しないことです。
sudo ls -hal /root/ > /root/test.out
私はただ応答を受け取ります:
-bash: /root/test.out: Permission denied
どうすればこれを機能させることができますか?
私は、開発中の RedHat Linux ボックスの 1 つで sudo アクセスを許可されており、通常は書き込みアクセスを持たない場所に出力をリダイレクトする必要があることがよくあるようです。
問題は、この不自然な例が機能しないことです。
sudo ls -hal /root/ > /root/test.out
私はただ応答を受け取ります:
-bash: /root/test.out: Permission denied
どうすればこれを機能させることができますか?
に書き込む権限がないシェルによってリダイレクトが実行されるため、コマンドは機能しません/root/test.out
。出力のリダイレクトはsudoによって実行されません。
複数の解決策があります:
sudoを使用してシェルを実行し、次の-c
オプションを使用してコマンドを実行します。
sudo sh -c 'ls -hal /root/ > /root/test.out'
コマンドを使用してスクリプトを作成し、sudoを使用してそのスクリプトを実行します。
#!/bin/sh
ls -hal /root/ > /root/test.out
を実行しますsudo ls.sh
。一時ファイルを作成したくない場合は、SteveBennettの回答を参照してください。
でシェルを起動してsudo -s
から、コマンドを実行します。
[nobody@so]$ sudo -s
[root@so]# ls -hal /root/ > /root/test.out
[root@so]# ^D
[nobody@so]$
使用sudo tee
(オプションを使用するときに多くのエスケープが必要な場合-c
):
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
ティーが画面に出力されないようにするには、へのリダイレクト/dev/null
が必要です。出力ファイル( )を上書きする代わりに追加するには、またはを使用します(最後のファイルはGNU coreutilsに固有です)。>>
tee -a
tee --append
Jd、Adam J. Forster、Johnathanの2番目、3番目、4番目のソリューションに感謝します。
ここの誰かが sudoing tee を提案しました:
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
これは、アクセス権のないディレクトリにコマンドをリダイレクトするためにも使用できます。これは、tee プログラムが事実上「ファイルへのエコー」プログラムであり、/dev/null へのリダイレクトにより、画面への出力も停止して、上記の元の不自然な例と同じに保つために機能するためです。
私が自分で見つけたトリックは
sudo ls -hal /root/ | sudo dd of=/root/test.out
問題は、コマンドは の下sudo
で実行されますが、リダイレクトはユーザーの下で実行されることです。これはシェルによって行われ、それについてできることはほとんどありません。
sudo command > /some/file.log
`-----v-----'`-------v-------'
command redirection
これをバイパスする通常の方法は次のとおりです。
sudo の下で呼び出すスクリプトにコマンドをラップします。
コマンドやログ ファイルが変更された場合、スクリプトがこれらを引数として受け取るようにすることができます。例えば:
sudo log_script command /log/file.txt
シェルを呼び出して、コマンド ラインをパラメーターとして渡します。-c
これは、1 回限りの複合コマンドの場合に特に便利です。例えば:
sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
必要な権限を持つパイプ/サブシェルを配置します (つまり、sudo)
# Read and append to a file
cat ./'file1.txt' | sudo tee -a '/log/file.txt' > '/dev/null';
# Store both stdout and stderr streams in a file
{ command1 arg; command2 arg; } |& sudo tee -a '/log/file.txt' > '/dev/null';
ティーオプションが望ましい理由を少し明確にする
出力を作成するコマンドを実行するための適切な権限があると仮定すると、コマンドの出力を tee にパイプする場合は、tee の権限を sudo で昇格させ、tee に問題のファイルに書き込む (または追加する) よう指示するだけで済みます。
質問に示されている例では、次のことを意味します。
ls -hal /root/ | sudo tee /root/test.out
いくつかのより実用的な例については:
# kill off one source of annoying advertisements
echo 127.0.0.1 ad.doubleclick.net | sudo tee -a /etc/hosts
# configure eth4 to come up on boot, set IP and netmask (centos 6.4)
echo -e "ONBOOT=\"YES\"\nIPADDR=10.42.84.168\nPREFIX=24" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth4
これらの各例では、非特権コマンドの出力を取得し、通常はルートのみが書き込み可能なファイルに書き込みます。これが質問の起源です。
出力を生成するコマンドは昇格された権限で実行されないため、この方法をお勧めします。ここでは問題にならないように見えますecho
が、source コマンドが完全に信頼できないスクリプトである場合、これは非常に重要です。
Note you can use the -a option to tee to append append (like >>
) to the target file rather than overwrite it (like >
).
テーマのさらに別のバリエーション:
sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF
またはもちろん:
echo 'ls -hal /root/ > /root/test.out' | sudo bash
sudo
またはsh
/への引数を覚える必要がないという (小さな) 利点があります。bash
次のように、sudoにシェルを実行させます。
sudo sh -c "echo foo > ~root/out"
私がこの問題に取り組む方法は次のとおりです。
ファイルの書き込み/置換が必要な場合:
echo "some text" | sudo tee /path/to/file
ファイルに追加する必要がある場合:
echo "some text" | sudo tee -a /path/to/file
死んだ馬を打ち負かすつもりはありませんが、ここには を使用する回答が多すぎます。つまり、画面にコピーを表示したくない場合を除き、tee
にリダイレクトする必要があります。stdout
/dev/null
より簡単な解決策は、次のcat
ように使用することです。
sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"
リダイレクションが引用符で囲まれていることに注意してください。これにより、リダイレクションは、それを実行しているシェルではなく、によって開始されたシェルによって評価されsudo
ます。
スクリプトを書いてみませんか?
ファイル名:myscript
#!/bin/sh
/bin/ls -lah /root > /root/test.out
# end script
次に、sudoを使用してスクリプトを実行します。
sudo ./myscript
私はこのようにします:
sudo su -c 'ls -hal /root/ > /root/test.out'
私がこのようなことをしなければならないときはいつでも、私はただルートになります:
# sudo -s
# ls -hal /root/ > /root/test.out
# exit
これはおそらく最善の方法ではありませんが、機能します。
これは、 に関する回答に基づいていますtee
。物事を簡単にするために、小さなスクリプト (私はそれを と呼びます) を書き、許可を得suwrite
てそれを入れました:/usr/local/bin/
+x
#! /bin/sh
if [ $# = 0 ] ; then
echo "USAGE: <command writing to stdout> | suwrite [-a] <output file 1> ..." >&2
exit 1
fi
for arg in "$@" ; do
if [ ${arg#/dev/} != ${arg} ] ; then
echo "Found dangerous argument ‘$arg’. Will exit."
exit 2
fi
done
sudo tee "$@" > /dev/null
コードのUSAGEに示されているように、出力をこのスクリプトにパイプし、その後にスーパーユーザーがアクセスできる目的のファイル名を指定するだけで、必要に応じてパスワードの入力を求めるプロンプトが自動的に表示されます (含まれているためsudo
)。
echo test | suwrite /root/test.txt
これは の単純なラッパーであるためtee
、tee の追加オプションも受け入れ-a
、同時に複数のファイルへの書き込みもサポートすることに注意してください。
echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt
/dev/
また、このページのコメントの 1 つで言及された懸念事項であった、デバイスへの書き込みに対する単純な保護も備えています。
一部のプログラム/パスへの sudo アクセスのみが許可されている可能性がありますか? それからあなたが望むことをする方法はありません。(何らかの方法でハッキングしない限り)
そうでない場合は、bash スクリプトを記述できます。
cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out
ctrl+を押すd:
chmod a+x myscript.sh
sudo myscript.sh
それが役立つことを願っています。