SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor

chmod 755 vs u+x: Perbezaan Mod Berangka dan Simbolik

Ketahui cara menggunakan chmod dengan mod berangka dan simbolik. Fahami mengapa chmod -R 755 merosakkan kebenaran direktori dan bagaimana penggunaan huruf X menyelesaikan masalah itu.

Perubahan yang dilakukan oleh chmod

chmod menukar bit kebenaran pada fail atau direktori, dan ia menerima bit tersebut dalam salah satu daripada dua notasi. Bentuk berangka ialah nombor perlapanan (octal) yang menggantikan setiap bit kebenaran sekaligus. Bentuk simbolik menamakan kelas pengguna dan operator, dan ia hanya menyunting bit yang anda nyatakan. Kedua-duanya berakhir dengan panggilan sistem yang sama. Perbezaannya ialah apa yang berlaku kepada bit yang tidak anda sebutkan.

Membaca mod dan menukar mod adalah tugas yang berbeza. Jika huruf dalam senarai panjang (long listing) belum jelas, baca maksud drwxr-xr-x mengikut medan terlebih dahulu. Panduan ini hanya menukar mod tersebut.

Jalankan semua arahan di sini sebagai pengguna log masuk biasa anda. Akaun root memintas pemeriksaan ini, jadi demonstrasi kebenaran yang dijalankan sebagai root tidak membuktikan apa-apa. Jika anda masih bekerja sebagai root pada pelayan baharu, cipta pengguna biasa dengan keistimewaan minimum dan kembali semula.

Menyediakan persekitaran sandbox yang boleh dibuang

cd "$(mktemp -d)"
touch notes.txt

mktemp -d mencipta direktori kosong di bawah /tmp dan memaparkan laluan yang dibuat, manakala penggantian arahan menghantar laluan tersebut terus kepada cd. Tiada apa-apa di bawah ini yang akan menyentuh fail yang penting kepada anda.

Satu arahan melaporkan hasil bagi setiap perubahan:

stat -c '%a %A %n' notes.txt

%a memaparkan mod sebagai nombor perlapanan (octal), %A memaparkan mod yang sama dalam bentuk huruf yang digunakan oleh senarai panjang (long listing), dan %n memaparkan nama. Dalam blok yang berikut, baris yang bermula dengan $ ialah perkara yang anda taip, dan baris di bawahnya ialah perkara yang dicetak oleh arahan tersebut. Jalankan arahan tersebut sendiri. Output pada mesin anda sepatutnya sepadan baris demi baris, kerana mod berangka tidak bergantung pada apa-apa dalam persekitaran anda.

Bentuk berangka: satu digit perlapanan bagi setiap kelas

Digit pertama adalah untuk pemilik fail. Digit kedua adalah untuk kumpulan fail tersebut. Digit ketiga adalah untuk semua orang lain. Setiap digit merupakan hasil tambah, satu nilai bagi setiap bit. Tetapkan satu bit pada satu masa dan baca apa yang dilaporkan oleh stat.

$ chmod 400 notes.txt
$ stat -c '%a %A %n' notes.txt
400 -r-------- notes.txt
$ chmod 200 notes.txt
$ stat -c '%a %A %n' notes.txt
200 --w------- notes.txt
$ chmod 100 notes.txt
$ stat -c '%a %A %n' notes.txt
100 ---x------ notes.txt

Huruf-huruf tersebut sejajar dengan digit-digit berkenaan. Selepas aksara jenis fail di hadapan, kumpulan tiga huruf pertama adalah milik pemilik, tiga huruf seterusnya adalah milik kumpulan, dan tiga huruf terakhir adalah milik semua orang lain. Tambahkan nilai-nilai tersebut untuk menggabungkan bit di dalam satu kelas.

$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt
$ chmod 700 notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod 750 notes.txt
$ stat -c '%a %A %n' notes.txt
750 -rwxr-x--- notes.txt

Mod berangka adalah mutlak. Ia menulis kesemua sembilan bit pada setiap pelaksanaan, jadi kelas yang tidak anda fikirkan pun akan turut ditulis.

$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt

Perintah kedua tidak menyatakan apa-apa tentang kumpulan atau orang lain, namun bit mereka tetap berubah. Itulah sifat bentuk berangka, dan itulah sebabnya bentuk berangka merupakan alat yang salah untuk suntingan kecil. (chmod juga mengendalikan bit setuid, setgid dan sticky, yang berada pada digit keempat sebelum digit-digit ini. Itu adalah topik berasingan, dan panduan ini hanya tertumpu kepada tiga digit tersebut.)

Bentuk simbolik: kelas, operator, kemudian bit

Tulis kelas dahulu. u ialah pemilik, g ialah kumpulan, o ialah semua orang lain, dan a ialah kesemuanya sekali gus. Kemudian operator: + menambah bit, - membuang bit, dan = menetapkan kelas tersebut kepada bit yang anda senaraikan sahaja dan mengosongkan bit yang lain. Kemudian bit itu sendiri, sebagai r, w atau x.

$ chmod 640 notes.txt
$ stat -c '%a %A %n' notes.txt
640 -rw-r----- notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt
$ chmod g-r notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod o=r notes.txt
$ stat -c '%a %A %n' notes.txt
704 -rwx---r-- notes.txt

Setiap arahan menyentuh satu kelas dan membiarkan kelas lain seperti sedia ada. Gabungkan klausa dengan koma tanpa ruang, dan chmod akan melaksanakannya dari kiri ke kanan.

$ chmod u=rw,go=r notes.txt
$ stat -c '%a %A %n' notes.txt
644 -rw-r--r-- notes.txt
$ chmod go= notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt

go= dengan tiada apa-apa selepas tanda sama dengan akan membuang setiap bit daripada kumpulan dan daripada semua orang lain. Itulah bentuk yang anda mahukan pada fail yang hanya boleh dibaca oleh pemiliknya, seperti bahagian peribadi bagi pasangan kunci SSH.

chmod juga boleh melaporkan kerjanya sendiri, yang penting di dalam skrip di mana tiada sesiapa yang melihat skrin.

chmod -v u+x notes.txt
chmod -v u+x notes.txt

-v mencetak satu baris untuk setiap fail yang diberikan kepadanya. Jalankan kedua-dua arahan dan bandingkan dua baris tersebut pada skrin anda: yang pertama menamakan fail dan melaporkan mod asal sebelum ditukar serta mod selepas ditukar, dan yang kedua melaporkan mod sebagai dikekalkan, kerana bit yang diminta untuk ditambah sudah pun ditetapkan. -c mencetak baris hanya apabila fail benar-benar berubah, jadi ia adalah pilihan yang lebih baik untuk disimpan dalam log.

chmod 755 berbanding u+x: notasi mana yang perlu digunakan

Mulakan daripada fail yang sama sebanyak dua kali dan bandingkan hasil yang ditinggalkan oleh setiap notasi.

$ chmod 640 notes.txt
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 640 notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt

Kedua-dua arahan menjadikan fail boleh laku (executable) untuk pemiliknya. Hanya satu daripadanya membiarkan dua kelas pengguna yang lain seperti asal. Gunakan mod numerik apabila anda mengetahui keadaan akhir yang tepat dan mahu ia dikuatkuasakan; ini adalah kes yang lazim dalam skrip penempatan (deployment script) yang mesti menghasilkan keputusan yang sama pada mesin yang belum pernah anda lihat. Gunakan mod simbolik apabila ayat dalam fikiran anda mengandungi tambah atau buang, kerana bentuk numerik tidak mempunyai cara untuk menyatakan biarkan bahagian itu tidak berubah.

Mod yang dimiliki oleh fail baharu tidak datang daripada chmod. Ia datang daripada umask proses yang mencipta fail tersebut. Jalankan umask dan umask -S dalam shell anda sendiri untuk melihat nilai yang berkuat kuasa di sana, dan jangkakan ia berbeza antara pengedaran (distribution), antara shell log masuk anda dengan servis systemd, serta antara satu akaun dengan akaun yang lain. Umask menetapkan mod bagi setiap fail baharu, jadi ia menentukan keadaan asal anda sebelum chmod dijalankan.

Fungsi bit execute pada direktori

Ini adalah salah faham yang paling banyak membuang masa. Pada fail biasa, bit execute bermaksud kernel boleh menjalankan fail tersebut. Direktori tidak mengandungi arahan, jadi tiada apa-apa di dalamnya untuk dijalankan. Pada direktori, bit execute bermaksud traversal: kebenaran untuk menyelesaikan nama di dalamnya. Untuk mencapai dir/file, anda memerlukannya pada dir. Bit read adalah kebenaran berasingan, dan ia membenarkan penyenaraian nama yang terkandung dalam direktori tersebut. Anda boleh memiliki salah satu tanpa yang lain, yang lebih mudah dipercayai setelah anda melihatnya berlaku sendiri.

$ mkdir vault
$ printf 'hello\n' > vault/secret.txt
$ chmod 600 vault/secret.txt
$ chmod 100 vault
$ echo vault/*
vault/*
$ cat vault/secret.txt
hello

Shell mencetak semula corak tersebut tanpa perubahan kerana mengembangkan vault/* bermaksud membaca direktori, dan glob yang tidak sepadan dengan apa-apa dilalui sebagai teks literal dan bukannya mencetuskan ralat. cat masih berfungsi kerana anda memberikan nama itu sendiri dan traversal dibenarkan. Sekarang, tukarkan kedua-dua bit tersebut.

$ chmod 400 vault
$ echo vault/*
vault/secret.txt
$ cat vault/secret.txt
cat: vault/secret.txt: Permission denied

Nama-nama tersebut kelihatan tetapi kandungannya tidak. Read memberi anda senarai. Execute memberi anda laluan masuk. Hampir setiap direktori yang anda gunakan memerlukan kedua-duanya.

$ chmod 500 vault
$ cat vault/secret.txt
hello

Mengapa chmod -R dengan mod berangka merosakkan struktur direktori

-R melayari keseluruhan struktur direktori dan menggunakan mod yang anda berikan kepada setiap item yang ditemui. Direktori dan fail data memerlukan bit yang berbeza, jadi satu nombor mutlak tidak mungkin tepat untuk kedua-duanya. Bina satu struktur direktori kecil dan lihat bagaimana ia menjadi salah.

$ mkdir -p site/css
$ touch site/index.html site/css/main.css
$ printf '#!/bin/bash\necho hi\n' > site/deploy.sh
$ chmod 755 site site/css site/deploy.sh
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.sh

Itu adalah susun atur yang diperlukan oleh direktori fail statik. Berikut adalah kesilapan rekursif yang pertama.

$ chmod -R 755 site
$ stat -c '%a %A %n' site/index.html site/css/main.css
755 -rwxr-xr-x site/index.html
755 -rwxr-xr-x site/css/main.css

Tiada apa-apa yang rosak, dan itulah masalahnya. Kesilapan ini tidak mengeluarkan sebarang amaran, jadi ia terus wujud dalam arahan yang disalin selama bertahun-tahun. Dua fail data kini dianggap sebagai program. Git menyimpan bit laksana (execute bit), jadi commit anda yang seterusnya akan membawa perubahan tersebut kepada sesiapa sahaja yang melakukan clone pada repositori, dan rsync serta tar akan membawanya ke setiap mesin yang anda salin struktur direktori tersebut.

Kesilapan rekursif yang kedua pula sangat ketara. Halakan mod tanpa bit laksana kepada direktori dan direktori tersebut akan tertutup.

$ chmod 644 site
$ stat -c '%a %A %n' site
644 drw-r--r-- site
$ echo site/*
site/css site/deploy.sh site/index.html
$ cd site
bash: cd: site: Permission denied
$ cat site/index.html
cat: site/index.html: Permission denied

Nama-nama fail masih disenaraikan kerana bit baca (read bit) masih kekal, namun setiap laluan melalui direktori tersebut tertutup kerana bit laksana telah dibuang. chmod -R 644 site melakukan perkara itu kepada setiap direktori dalam struktur tersebut dalam satu arahan. Apa yang anda temui selepas itu juga tidak selalunya seragam, kerana chmod perlu melayari direktori yang sama yang aksesnya sedang disekat, jadi periksa apa yang sebenarnya berlaku dengan find site -type d -exec stat -c '%a %n' {} + dan jangan sekadar membuat andaian. Kembalikan tetapan ini sebelum meneruskan.

$ chmod 755 site
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/index.html
755 drwxr-xr-x site
644 -rw-r--r-- site/index.html

Arahan chmod rekursif tidak mempunyai fungsi buat asal (undo). chmod tidak merekodkan apa yang telah digantikannya, jadi kerja pembaikan terletak pada anda, iaitu membina semula mod berdasarkan apa yang anda percaya sepatutnya ada. Ia adalah kerja yang perlahan dan tidak pasti, sama seperti membina semula fail selepas rm -rf secara tidak sengaja, dan pengajarannya tetap sama: periksa sasaran arahan rekursif sebelum anda menekan enter.

Huruf X besar: laksanakan pada direktori, bukan pada setiap fail

Mod simbolik menerima X dan juga x. X menetapkan bit laksana (execute bit) hanya pada tempat yang wajar: pada direktori, atau pada fail biasa yang sudah mempunyai bit laksana untuk mana-mana kelas. Peraturan tersebut adalah tepat seperti peraturan yang anda mahukan untuk diikuti oleh -R.

$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.sh

Satu arahan sahaja, dan direktori kekal boleh dilayari manakala fail data tidak disentuh. Skrip tersebut mengekalkan bit laksananya kerana ia sudah pun memilikinya, yang merupakan separuh kedua daripada peraturan X. X membaca mod yang dimiliki oleh fail pada masa ini, jadi fail yang telah kehilangan setiap bit laksana tidak boleh dikembalikan semula olehnya.

$ chmod 644 site/deploy.sh
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site/deploy.sh
644 -rw-r--r-- site/deploy.sh
$ site/deploy.sh
bash: site/deploy.sh: Permission denied
$ chmod u+x site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
744 -rwxr--r-- site/deploy.sh
$ site/deploy.sh
hi

Peraturan yang sama berfungsi secara sebaliknya. X akan melanjutkan bit laksana yang sudah dimiliki oleh fail kepada kelas lain:

$ chmod go+X site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
755 -rwxr-xr-x site/deploy.sh

Jadi, x huruf kecil adalah untuk satu fail bernama yang anda ingin jadikan boleh laksana, dan X adalah untuk imbasan merentasi pepohon direktori. Apabila anda mahukan mod yang tepat bagi setiap jenis perkara dan bukannya peraturan berdasarkan mod semasa, asingkan proses tersebut dengan find sebaliknya.

find site -type d -exec chmod 755 {} +
find site -type f -exec chmod 644 {} +
chmod u+x site/deploy.sh

-type d memilih direktori dan -type f memilih fail biasa, jadi setiap jenis mendapat mod yang sepatutnya. -exec ... + mengumpulkan banyak laluan ke dalam satu panggilan chmod dan bukannya memulakan satu proses bagi setiap fail, yang penting bagi pepohon dengan ribuan entri. Skrip tersebut mendapat semula bitnya pada baris yang berasingan, secara sengaja.

Semak hasil sebelum anda beredar

Dua arahan akan mencari kesilapan yang penting selepas sebarang perubahan rekursif. Arahan pertama menyenaraikan direktori yang tidak lagi boleh anda masuki.

find . -type d ! -perm -u+x

Arahan kedua menyenaraikan fail yang boleh disunting oleh mana-mana akaun pada mesin tersebut.

find . -type f -perm -o+w

Dalam -perm -o+w, - di hadapan bermaksud sekurang-kurangnya bit ini, jadi ia memadankan fail yang kelas o-nya mempunyai bit tulis tidak kira apa lagi yang ditetapkan. Tiada output daripada kedua-dua arahan ini adalah hasil yang anda mahukan. Jalankan kedua-duanya dari bahagian atas mana-mana pepohon yang baru anda ubah dengan -R, dan jalankan stat -c '%a %A %n' pada beberapa laluan yang anda ingin ubah, supaya mod yang anda tetapkan adalah mod yang sebenarnya dipegang oleh kernel.

FAQ

Apakah perbezaan antara chmod 755 dan chmod u+x?

Mod berangka adalah mutlak. Ia menulis setiap bit kebenaran pada fail, jadi kelas yang tidak anda fikirkan akan ditulis semula juga. Mod simbolik adalah satu suntingan. u+x menambah satu bit untuk pemilik dan membiarkan setiap bit lain seperti sedia ada. Gunakan bentuk berangka apabila anda mengetahui keadaan akhir yang tepat yang anda mahukan pada sesuatu fail. Gunakan bentuk simbolik apabila anda ingin menambah atau membuang satu perkara. Jalankan stat -c '%a %A %n' <file> sebelum dan selepas mana-mana arahan dan perbezaannya akan muncul dalam output.

Mengapa chmod -R 755 pada direktori fail web adalah idea yang buruk?

Kerana -R menghantar mod mutlak yang sama kepada direktori dan fail biasa, sedangkan kedua-duanya memerlukan bit yang berbeza. Direktori memerlukan bit laksana (execute) untuk dilalui. Fail data seperti HTML dan CSS tidak memerlukannya, dan menandakannya sebagai boleh laksana adalah perubahan yang direkodkan oleh git dalam commit anda yang seterusnya dan disalin oleh rsync ke mesin seterusnya. Gunakan chmod -R u=rwX,go=rX <dir> supaya bit laksana hanya diletakkan pada direktori, atau uruskannya daripada find dengan -type d dan -type f supaya setiap jenis mendapat modnya sendiri.

Apakah fungsi bit laksana pada direktori?

Ia memberikan kebenaran untuk melintasi, bukan melaksanakan. Tiada apa-apa di dalam direktori untuk dijalankan. Bit laksana adalah kebenaran untuk menyelesaikan nama di dalamnya, jadi anda memerlukannya pada setiap direktori sepanjang laluan sebelum anda boleh membuka fail di hujung laluan tersebut. Bit baca adalah berasingan dan memberikan kebenaran untuk menyenaraikan nama. Anda boleh memegang satu tanpa yang lain: dengan bit laksana sahaja anda boleh membuka fail yang namanya sudah anda ketahui sementara shell tidak boleh mengembangkan glob dalam direktori tersebut, dan dengan bit baca sahaja anda boleh melihat nama-nama tersebut sementara setiap percubaan untuk membukanya akan gagal.

Bilakah saya perlu menggunakan huruf besar X dan bukannya huruf kecil x?

Gunakan X apabila arahan tersebut bersifat rekursif. X menetapkan bit laksana pada direktori, dan pada fail biasa hanya apabila satu bit laksana sudah ditetapkan, jadi satu laluan menjadikan pepohon boleh dilalui tanpa menukarkan fail data menjadi program. Gunakan huruf kecil x apabila anda merujuk kepada satu fail dan anda bermaksud fail itu sahaja. Satu had yang perlu diingat: X tidak boleh memulihkan bit laksana yang telah dipadamkan di mana-mana pada fail, kerana ia tidak mempunyai apa-apa lagi untuk dipadankan. Kembalikan bit tersebut dengan chmod u+x <file>.

Adakah chmod menukar pemilik fail?

Tidak. chmod hanya menukar bit kebenaran. Pemilikan adalah milik chown untuk pengguna dan chgrp untuk kumpulan, dan menyerahkan fail kepada pengguna lain memerlukan root. Ini penting kerana bit tersebut dibaca berdasarkan pemilik dan kumpulan yang direkodkan pada fail, bukan berdasarkan siapa yang menulisnya kali terakhir. Jalankan stat -c '%U %G %a %n' <file> untuk melihat pemilik, kumpulan dan mod bersama-sama sebelum anda memutuskan mana antara tiga arahan tersebut yang sebenarnya anda perlukan.