sudoでリダイレクトするとPermission deniedとなってしまった
sudoを実行しているユーザの権限が無いファイルにリダイレクトで書き込みをしたところPermission deniedとなってしまったので、その原因と解決方法を調べた結果をまとめました。
実際の失敗例
echoで表示させた文字列をファイルにリダイレクトさせて書き込もうとした際に、Permission deniedとなってしまいました。
$ sudo echo test > /usr/share/nginx/html/test.html -bash: /usr/share/nginx/html/test.html: Permission denied
今回はechoの結果をリダイレクトさせていますが、他のコマンドの実行結果をファイルにリダイレクトさせても同様にPermission deniedとなります。
原因
調べてみたところ、原因としてはsudoの効果がechoまでしか届いていなく、リダイレクト部分は実際のユーザ権限で実行しているため「Permission denied」となるということがわかりました。
検証
sudoを実行するユーザが書き込みを行うことができる、ユーザのホームディレクトリでリダイレクトでファイルに書き込みを行って、作成されるファイルの所有者を確認してみます。
$ whoami tamohiko $ cd $ sudo echo test > test.txt $ ls -l test.txt -rw-rw-r-- 1 tamohiko tamohiko 5 Dec 8 15:47 test.txt
作成されたtest.txtファイルの所有者が、sudoを実行したユーザでありrootではないことが確認できました。
解決方法
解決方法として調べたところ下記の2つが見つかりました。
- sudo sh -c "コマンド > ファイル"
- コマンド | sudo tee ファイル
teeコマンドを使用する方法はリダイレクションを使用しない方法となっています。
sudo sh -c
sh -cを使ってコマンドを読み込ませて実行することで一つのコマンドとして認識され、コマンドがsudoで実行されるためリダイレクトでファイルに書き込みをすることができます。
$ sudo sh -c "echo test > /usr/share/nginx/html/test.html" $ cat /usr/share/nginx/html/test.html test
作成されたファイルの所有者もrootとなっています。
$ ls -l /usr/share/nginx/html/test.html -rw-r--r-- 1 root root 12 Dec 8 00:32 /usr/share/nginx/html/test.html
このやり方は、sudoのmanにも例として記載されていました。
To make a usage listing of the directories in the /home partition. Note that this runs the commands in a sub-shell to make the cd and file redirection work.
$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
コマンド | sudo tee ファイル
リダイレクトは使用しませんが、echoで表示させたものを|(パイプ)でsudo teeに渡すことでファイルへの書き込みが出来ます。
この場合、sudoで実行しているのがteeコマンドなので書き込みできるようになります。
$ echo test2 | sudo tee /usr/share/nginx/html/test.html test2 $ cat /usr/share/nginx/html/test.html test2
どこかで見たことあると思ったら、このやり方はUbuntuとかでリポジトリを追加する際に使用されていました。
下記はUbuntuでnginxのリポジトリを追加する場合に実行するコマンドですが、echoで表示させたものをsudo teeでファイルに書き込みを行っています。
$ echo "deb http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
追記したいときは-aオプションを使用
teeコマンドでファイルに追記をしたい場合は-aオプションを指定します。
$ echo test3 | sudo tee -a /usr/share/nginx/html/test.html test3 $ cat /usr/share/nginx/html/test.html test2 test3
コメント