sudoでリダイレクトするとPermission deniedとなってしまう場合の解決方法

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

シェアする