chmodコマンド|読み書き実行を誰に許すかを決める
chmod コマンドを調べる場面は、だいたい2つに絞られます。書いたシェルスクリプトを動かそうとして permission denied が返ったとき、そして誰かの手順書に chmod 755 と書いてあって、その3桁が何を指しているのか分からないときです。どちらも、ファイルに付いている許可のスイッチがいくつあって、どの順番で並んでいるかを知れば、その場で組み立てられるようになります。数字の書き方と記号の書き方、macOSにだけある仕組み、そして権限を変えても症状が直らないときの切り分けまで、順に押さえます。
chmodが動かしているのは、ファイルに付いた9個のスイッチ
chmod は change mode の略で、ファイルやディレクトリに付いている「ファイルモード」を書き換えるコマンドです。ファイルモードのうち普段扱うのは、3人の相手に対する3種類の許可、つまり9個のスイッチです。相手は、所有者(user)、所有グループ(group)、それ以外の全員(other)の3つ。許可は、読む(read)、書く(write)、実行する(execute)の3つです。
ls -l の出力の先頭に並ぶ -rwxr-xr-x のような文字列が、そのスイッチの状態をそのまま表しています。先頭1文字は種類(ファイルなら -、ディレクトリなら d、シンボリックリンクなら l)で、続く9文字を3文字ずつに区切ると、所有者、グループ、その他の順になります。許可があれば r w x が、なければ - が立ちます。
3つ目の x は、相手がファイルかディレクトリかで意味が変わります。説明書では、ファイルに対しては実行を許す、ディレクトリに対しては「そのディレクトリの中を検索することを許す」と書き分けられています。ディレクトリの x を外すと、中にある名前を知っていても辿り着けなくなります。逆に r だけを外すと、一覧は出せないのに名前を指定すれば開ける、という中途半端な状態になります。ディレクトリでは r と x を揃えるのが原則です。
この仕組みは、いま作られたものではありません。macOSに入っている説明書の履歴欄には、chmod は Version 1 AT&T UNIX から存在すると書かれています。Macで覚えた書き方がそのままLinuxのサーバーで通じるのは、半世紀ほど前に決まった形をどちらも引き継いでいるからです。
chmodコマンドは、change modeに由来するコマンドで、 ファイルモード(ファイルのアクセス権限など)を変更できます。 出典: skume.net
数字で指定する書き方は、4と2と1の足し算だけ
chmod 755 script.sh のような書き方を、絶対モードと呼びます。3桁の数字は、左から所有者、グループ、その他に対応します。各桁の値は、読みが4、書きが2、実行が1で、許したいものを足した合計です。
- 7は 4+2+1 で、読み書き実行のすべて
- 6は 4+2 で、読みと書き
- 5は 4+1 で、読みと実行
- 4は読みだけ
- 0は何も許さない
説明書自身が、755 について「所有者に読み書き実行を許し、グループとその他に読みと実行を許し、set-uid も set-gid も付けない絶対モードは 755(400+200+100+040+010+004+001)である」と例示しています。桁で覚えるより、4と2と1の足し算だと覚えたほうが応用が効きます。
実務で出てくる組み合わせは、そう多くありません。スクリプトやコマンドは 755、自分だけが実行するものは 700、設定ファイルやテキストは 644、認証情報や秘密鍵を含むファイルは 600、共同編集するディレクトリは 775 です。SSHの鍵ファイルが 600 でないと拒否される話も、この表の中の出来事です。
やってはいけないのが 777 です。その他の全員に書き込みを許すという指定で、同じMacを使う別のアカウントも、そのファイルを書き換えたり消したりできる状態になります。「権限で困ったら 777」という手順書を見かけますが、これは症状を隠すだけで、原因はたいてい所有者の違いか、次に説明するACLです。
記号で指定する書き方は、誰に、何を、どうするか
記号モードは、いまの状態を保ったまま一部だけを足したり引いたりするときに使います。書き方は「誰に」「どうする」「何を」の3つを並べるだけです。
- 誰に:
u(所有者)、g(グループ)、o(その他)、a(全員。ugoと同じ) - どうする:
+(足す)、-(引く)、=(その値にする) - 何を:
r、w、x、s(set-uid と set-gid)、t(スティッキービット)
chmod +x script.sh が実行の許可を足す指定、chmod go-w report.txt がグループとその他から書き込みを外す指定です。カンマで区切れば、1回の呼び出しで複数の指定をまとめられます。説明書が挙げている u=rwx,go=rx は、755 とまったく同じ意味です。
記号モードにしかない値が2つあります。1つは大文字の X で、「ディレクトリである場合、または元のモードでいずれかの実行ビットが立っている場合にのみ、実行ビットを立てる」と定義されています。もう1つは u g o を「何を」の位置に置く書き方で、chmod g=u-w file と書くと、グループの許可を所有者と同じにしたうえで書き込みだけを落とせます。
もう1つ知っておくと得なのが、「誰に」を省いたときの挙動です。説明書では、誰にを省いた + は、ファイルモード作成マスク(umask)で落とされていないビットだけを立てると定義されています。chmod +w が思ったように効かないことがあるのは、この umask が挟まっているからです。相手をはっきりさせたいときは a+w のように省略せずに書きます。
フォルダごと変えるときは、ファイルまで実行可能にしない
-R を付けると、指定したディレクトリの下にあるものすべてに同じ指定が及びます。ここで最もよく起きる事故が chmod -R 755 です。ディレクトリは通ってほしいので x が要りますが、同じ指定が中のテキストやPDFにも当たり、すべてのファイルに実行の許可が付きます。Gitで管理しているフォルダに当てると、変更点が数百件並ぶことになります。
正しい道は2つあります。1つは大文字の X を使う方法で、説明書が例として載せている =rw,+X は「読みと書きを通常の既定値に設定し、いま立っている実行の許可は残す」という意味です。ディレクトリと、もともと実行可能だったファイルにだけ x が付きます。
もう1つは find でファイルとディレクトリを分ける方法です。-type d と -type f で対象を分け、それぞれに違うモードを当てます。find の説明書では、-exec ユーティリティ {} + の形は「{} が可能な限り多くのパス名で置き換えられる」と定義されていて、1件ごとに chmod を起動する ; の形より呼び出し回数が減ります。件数が万を超えるフォルダでは、この差がそのまま待ち時間の差になります。
-R と一緒に使う -H -L -P は、シンボリックリンクを辿るかどうかの指定です。既定は -P で、リンクは辿りません。説明書にはもう1つ注意が書かれています。.* のようなワイルドカードを使うと、親ディレクトリを指す .. に意図せず一致することがある、という警告です。ホームディレクトリで隠しファイルをまとめて変えようとして、ホームより上まで巻き込む事故がこれに当たります。
macOSのchmodはACLも扱う。ls -l の末尾の記号がその印
ここから先はmacOSに固有の話で、Linux向けの解説にはほとんど出てきません。macOSのchmodは、9個のスイッチに加えてACL(アクセス制御リスト)も書き換えます。ACLは相手ごとの許可と禁止を並べた一覧で、9個のスイッチでは表せない細かい指定ができます。説明書には delete(項目の削除)、readattr(基本属性の読み取り)、writesecurity(所有権やACLの書き換え)といった許可の名前が並んでいます。
追加は chmod +a "admin allow write" file1 のように書き、削除は -a、番号を指定した書き換えは =a# です。中身を見るには ls -le を使います。-e は「ファイルに付いているACLを長い形式の出力に表示する」オプションだと定義されています。
ここで見落としやすいのが、ls -l の許可の欄のうしろに付く記号の意味です。ls の説明書は順番まで決めています。拡張属性があれば @ が付き、拡張属性がなくACLのような拡張セキュリティ情報があれば + が付く、と書かれています。つまり拡張属性が付いているファイルでは、ACLがあっても @ が優先されて表示されます。@ が出ているファイルでACLを確かめたいときは、ls -le で直接見るしかありません。
実務でこれが効くのは、権限の表示が -rw-r--r-- なのに書き込みを拒否される、あるいはその逆の場面です。9個のスイッチだけを見て「権限は合っている」と判断すると、ACLの deny 行に気づけません。chmod -N でACLをまるごと外す、chmod -C で並び順が正しいかを調べる、といった手も同じコマンドの中にあります。
setuid・setgid・スティッキービットの3つの特別なビット
9個のスイッチの上に、3つの特別なビットがあります。数字で書くときは4桁目に置きます。
- 4000(setuid): 実行ファイルに付けると、実行した人ではなくファイルの所有者の権限で動く
- 2000(setgid): 実行ファイルに付けると、所有グループの権限で動く
- 1000(スティッキービット): ディレクトリに付けると、中のファイルを消せる人を絞る
スティッキービットは、macOSに入っている sticky の説明書が用途をはっきり書いています。スティッキービットが立ったディレクトリは、ファイルの削除が制限されたディレクトリになり、書き込みの許可を持っていても、そのファイルの所有者かディレクトリの所有者か管理者でなければ削除や改名ができない。誰でも書き込める必要があるが、互いのファイルを勝手に消させたくない /tmp のような場所に向いている、と説明されています。同じ説明書には、open も mkdir もスティッキービットが立ったファイルを作ることはない、という但し書きも付いています。
setuid と setgid は、自分で付ける機会はほとんどありません。付けたファイルは、実行した人の権限を離れて動くため、書き方を誤ると誰でも所有者の権限を借りられる穴になります。ls -l では実行の位置が s と表示されるので、覚えのないファイルに s が立っていたら、まず出どころを確かめる場面です。
権限を変えても症状が直らないときの見分け方
chmod を打ったのに状況が変わらないときは、原因が権限の外にあります。順に当たれば切り分けられます。
最初に確かめるのは、自分がそのファイルの所有者かどうかです。説明書には「ファイルの所有者かスーパーユーザーだけが、ファイルのモードを変更できる」と明記されています。他のアカウントが作ったファイルは、chmod ではなく所有者の変更(chown)の話になります。
次に、そのファイルが置かれているボリュームの形式です。外付けのUSBメモリやSDカードでよく使われるexFATやMS-DOS形式は、ファイルごとの許可を持っていません。macOSの mount_exfat の説明書によれば、許可はマウントするときの -m で決まる上限であり、-u -g -m のどれも指定しないと、ボリュームは所有権を無視する扱いでマウントされます。この状態のボリュームでは、chmod を打っても結果が残りません。ネットワーク共有も似ていて、mount_smbfs の説明書は、マウント時に指定した許可はSMBサーバーが実際に与えている権限と異なる場合がある、と注意しています。
3つ目は、権限とは別の層にある拡張属性です。インターネットから落としたファイルには隔離の印が付き、権限とは無関係に起動が止められます。拡張属性は xattr で一覧でき、ls -l@ でも名前と大きさを表示できます。chmod +x を何度打っても状況が動かないダウンロード済みのコマンドは、ここを見る場面です。
4つ目は、対象がシンボリックリンクだった場合です。既定ではリンクの先が変わります。リンクそのものの許可を変えたいときは -h を付けます。
Finderの画面から変える道と、ターミナルから変える道
Macには、chmod を打たずに許可を変える道もあります。Appleのユーザガイドは、Finderの「情報」ウインドウの下部で設定を変えられると説明しています。
アクセス権の設定によって、コンピュータのファイルを表示および変更できるユーザが決まります。ファイル、フォルダ、またはディスクの「情報」ウインドウの下部にあるアクセス権の設定は、Finderで変更できます。 出典: support.apple.com
手順は、対象を選んで「ファイル」>「情報を見る」、「共有とアクセス権」を開き、鍵を外してから相手ごとに設定を選ぶ形です。選べるのは「読み/書き」「読み出しのみ」「書き込みのみ(ドロップボックス用)」「アクセス不可」の4つ。フォルダの下にあるものすべてに同じ設定を当てたいときは「内包している項目に適用」を選びます。これが chmod -R に当たる操作です。
この画面でできないことがはっきりあります。実行の許可を単独で付けられません。setuid も setgid もスティッキービットも触れません。数字で 750 のように狙った値を指定することもできません。つまり、読み書きだけを人単位で調整するならFinderで足り、スクリプトを動かす、鍵ファイルを締める、共有ディレクトリの削除を絞るといった用途になった時点で、ターミナルに移る必要があります。
同じ窓で確かめてから打つと、対象の取り違えが起きない
権限の作業で怖いのは、書き方を間違えることよりも、対象を間違えることです。chmod -R は1文字の打ち間違いで効く範囲が変わり、実行したあとに「どこに当たったのか」を戻って確かめる手段がありません。事故の多くは、フォルダを見ている窓とコマンドを打つ窓が別で、いまどのフォルダに居るのかを思い込みで補っていたことから起きています。
そこで効くのが、フォルダとターミナルとAIが同じ窓にあるという構えです。左で対象のフォルダを選び、その場所に紐づいたターミナルで ls -le を打ち、結果を見てから chmod を当てる。フォルダを切り替えればターミナルの居場所も一緒に動くので、cd の打ち直しも、パスの貼り付けも要りません。ファイル管理アプリに何が入っているかはできることにまとまっています。
権限の話は、AIに手伝わせる場面とも相性があります。やりたいことを日本語で書けばコマンドになり、左の一覧は視界から消えません。ただし権限を変える指定は戻せないので、当てる前に対象を目で確かめる手順は残したほうが安全です。この点は他のファイル管理との比較で、エディタ側に寄った道具との違いとして整理されています。
外に出ているあいだにサーバーの権限を直したい、という場面もあります。手元のiPhoneやiPadから自宅のMacのターミナルを読んで打ち込めるようにする仕組みはiPhone・iPadから続きをにあります。Mac単体で使う範囲は無料で期限がなく、iPhoneとiPadから使う分だけが有料という区切りは料金に、対応するmacOSの版や必要な設定はよくある質問に載っています。
よくある質問
chmod 755 と chmod 644 はどう使い分けますか?
755はシェルスクリプトやコマンドのように実行するファイル、644は設定ファイルやテキストのように読むだけのファイルに使います。どちらも所有者だけが書き込めて、他の人は読めるという点は同じで、違いは実行の許可があるかどうかです。認証情報を含むファイルは、他の人に読ませないために600にします。
chmod 777 を使ってはいけないのはなぜですか?
777は、そのMacを使う他のアカウントを含めた全員に、読み書きと実行のすべてを許す指定です。中身を書き換えられても消されても止められません。権限で困る場面の原因は、たいてい所有者の違いかACLの禁止行なので、777にしても症状が隠れるだけで直っていません。
フォルダごと変えると、中のテキストまで実行可能になってしまうのはなぜですか?
chmod -R 755 は中身の種類を区別しないためです。大文字のXを使う chmod -R =rw,+X なら、ディレクトリともともと実行可能だったファイルにだけ実行の許可が付きます。種類ごとに違う値を当てたいときは、findで -type d と -type f に分けて指定します。
chmod を打ったのに権限が変わらないのはなぜですか?
まず自分がそのファイルの所有者かを確かめます。所有者か管理者でなければモードは変えられません。次にボリュームの形式です。exFATやMS-DOS形式、ネットワーク共有は、許可をマウント時の設定で決めるため、個別のchmodが残りません。ダウンロードしたファイルが動かない場合は、権限ではなく拡張属性の隔離の印が原因のことがあります。