web-dev-qa-db-ja.com

Sudoを使用して、書き込み権限のない場所に出力をリダイレクトする方法

私は私たちの開発RedHat Linuxボックスの1つにSudoアクセス権を与えられました、そして私は私自身が通常は書き込みアクセス権を持っていない場所に出力をリダイレクトする必要があるようです。

問題は、この人為的な例は機能しないことです。

Sudo ls -hal /root/ > /root/test.out

私はただ応答を受けます:

-bash: /root/test.out: Permission denied

これを機能させるにはどうすればよいですか。

786
Jonathan

/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を実行してください。一時ファイルを作成したくない場合は、Steve Bennettの answer を参照してください。

  • 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
    

    tee を画面に出力しないようにするには、/dev/nullへのリダイレクトが必要です。出力ファイル(>>)を上書きする代わりにappendにするには、tee -aまたはtee --appendを使用します(最後のものは GNU coreutils に固有です)。

JdAdam J. Forster および Johnathan にアクセスして、2番目、3番目、4番目の解決策を見つけてください。

1096

ここで誰かがTシャツをすくうことを提案したばかりです:

Sudo ls -hal /root/ | Sudo tee /root/test.out > /dev/null

これはまた、あなたがアクセスできないディレクトリに任意のコマンドをリダイレクトするのにも使用できます。これは、teeプログラムが事実上「ファイルへのエコー」プログラムであり、/ dev/nullへのリダイレクトが画面への出力も停止して上記の元の人為的な例と同じになるためです。

91
Jonathan

私が考え出したトリックは

Sudo ls -hal /root/ | Sudo dd of=/root/test.out
71
rhlee

問題は、 コマンド 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"
    
41
dsm

テーマに関するさらに別のバリエーション:

Sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

またはもちろん:

echo 'ls -hal /root/ > /root/test.out' | Sudo bash

Sudosh/bashへの引数を覚えておく必要がないという小さな利点があります。

20
Steve Bennett

teeオプションが望ましい理由を少し明確にします

出力を作成するコマンドを実行するための適切な権限があると仮定して、コマンドの出力を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

これらの各例では、特権を持たないコマンドの出力を受け取り、通常はrootのみが書き込み可能なファイルに書き込みます。これが問題の原因です。

出力を生成するコマンドは昇格された特権で実行されないため、このようにすることをお勧めします。ここでechoを使用しても問題ないようですが、sourceコマンドが完全に信頼できないスクリプトである場合、それは非常に重要です。

-aオプションを使用すると、ターゲットファイルを上書きするのではなく(>>のように)append(>のように)を追加することができます。

18
jg3

このように、Sudoにシェルを実行させます。

Sudo sh -c "echo foo > ~root/out"
16
Penfold

私がこの問題について取り組む方法は次のとおりです。

あなたがファイルを書く/置き換える必要があるならば:

echo "some text" | Sudo tee /path/to/file

ファイルに追加する必要がある場合

echo "some text" | Sudo tee -a /path/to/file
9

スクリプトを書くのはどうですか?

ファイル名:myscript

#!/bin/sh

/bin/ls -lah /root > /root/test.out

# end script

次にSudoを使ってスクリプトを実行します。

Sudo ./myscript
5
Jd

私はこうします:

Sudo su -c 'ls -hal /root/ > /root/test.out'
4
fardjad

このようなことをしなければならないときはいつでも、私はただrootになります。

# Sudo -s
# ls -hal /root/ > /root/test.out
# exit

これはおそらく最善の方法ではありませんが、うまくいきます。

3
Adam J. Forster

死んだ馬を倒すつもりはありませんが、ここではteeを使用する回答が多すぎます。つまり、画面上でコピーを見たいのでない限り、stdout/dev/nullにリダイレクトする必要があります。もっと簡単な解決策は、このようにcatを使うことです:

Sudo ls -hal /root/ | Sudo bash -c "cat > /root/test.out"

リダイレクトが引用符で囲まれているため、実行中のシェルではなくSudoで開始されたシェルによって評価されます。

3
haridsv

これは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つで言及されている問題です。

2
jamadagni

たぶんあなたはSudoにいくつかのプログラム/パスだけへのアクセスを与えられましたか?それならあなたが望むことをする方法はありません。 (あなたが何らかの形でそれをハックしない限り)

そうでない場合は、おそらくbashスクリプトを書くことができます。

cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out 

押す ctrl + d :

chmod a+x myscript.sh
Sudo myscript.sh

お役に立てば幸いです。

1
user15453
Sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  
0
user8648126