シェルでファイルにリダイレクトしたときに”Permission denied”と怒られたときの対処
Contents
はじめに
定期的に質問される問題について。
「パイプで繋いで処理した情報を別ファイルにリダイレクトしたいが、実行ユーザの書き込み権限がないために Permission denied
が発生してしまい良い方法がないか?」
検証環境
$ uname -moi
x86_64 x86_64 GNU/Linux
$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
具体例
前提
- 処理実行ユーザは
root
のような/etc
ディレクトリ配下を編集する権限はない - ただし、
sudo
を使えば変更が可能 +/etc
配下にファイルを書き込みたい
実行したい内容
/etc/passwd
ファイルをフィルタリングして、 /etc/passwd.bk
を作りたいとします。
# "genzouw" さんのユーザだけをバックアップしておきたい
$ grep genzouw /etc/passwd
genzouw:x:1000:1000::/home/genzouw:/bin/zsh
# > で書き出ししたいが権限がないと怒られる
$ grep genzouw /etc/passwd > /etc/passwd.bk
bash: /etc/passwd.bk: Permission denied
余談ですが、上記メッセージは以下の言語設定のときのメッセージです。
$ expr $LC_ALL
en_US.UTF-8
言語設定を日本語に変更されている場合は以下のようなメッセージが表示されます。
$ LC_ALL=ja_JP.UTF-8
$ grep genzouw /etc/passwd > /etc/passwd.bk
bash: /etc/passwd.bk: 許可がありません
sudo grep
では解決しない
すぐに思いつくのは sudo
を使う方法です。
$ sudo grep genzouw /etc/passwd > /etc/passwd.bk
bash: /etc/passwd.bk: Permission denied
上記の通り、これでは問題が解決しません。grep
コマンドは sudo
つまり root
ユーザで実行していますが、リダイレクト処理(>
)は一般ユーザで実行されるためです。
sudo tee
コマンドを使う
sudo tee
を利用すれば解決できます。
teeコマンドは標準入力の内容を指定されたファイルに書き出しつつ、引数に指定されたファイルに書き出します。
( 入力を2つの出力に流すフローが T字 に見えることからこの名前がつけられています。 )
$ grep genzouw /etc/passwd | sudo tee /etc/passwd.bk
genzouw:x:1000:1000::/home/genzouw:/bin/zsh
# 一般ユーザでは閲覧できません!
$ cat /etc/passwd.bk
cat: /etc/passwd.bk: Permission denied
# 閲覧にもsudoが必要
$ sudo cat /etc/passwd.bk
genzouw:x:1000:1000::/home/genzouw:/bin/zsh
ファイルを追記したいときには
>
で上書きするような挙動だけでなく、 >>
で追記するような挙動をさせたい場合はどうしたらよいでしょう?
これも sudo tee
で実現可能です。-a
オプションを付与してやります。
# 先程のファイルに同じ内容を1行追加
$ grep genzouw /etc/passwd | sudo tee -a /etc/passwd.bk
genzouw:x:1000:1000::/home/genzouw:/bin/zsh
$ sudo cat /etc/passwd.bk
genzouw:x:1000:1000::/home/genzouw:/bin/zsh
genzouw:x:1000:1000::/home/genzouw:/bin/zsh
ひとこと
よく知られた方法ではありますが、僕もよく忘れて何度も遭遇するエラーメッセージです。
ディスカッション
コメント一覧
まだ、コメントがありません