Bagaimana cara tes non-invasif untuk akses tulis ke file?


20

Dalam skrip shell, bagaimana cara saya dengan mudah dan non-invasif menguji akses tulis ke file tanpa benar-benar mencoba untuk memodifikasi file?

Saya dapat mem-parsing output stat, tetapi itu tampaknya sangat kompleks, dan mungkin rapuh, meskipun saya tidak yakin berapa banyak output stat berbeda di seluruh implementasi dan waktu.

Saya dapat menambahkan ke akhir file dan melihat apakah itu berhasil, tetapi itu berpotensi berbahaya, karena dua alasan yang dapat saya pikirkan:

  1. Saya sekarang harus menghapus tambahan, dan kalau-kalau ada proses lain menulis ke file, ini segera menjadi non-sepele karena baris saya tidak lagi yang terakhir.
  2. Setiap proses membaca file mungkin memiliki persyaratan sewenang-wenang pada konten file itu, dan saya mungkin telah merusak aplikasi itu.

Jawaban:


29

Cukup gunakan - wflag testutillity:

[ -w /path/to/file ] && echo "writeable" || echo "write permission denied"

Perhatikan bahwa jika Anda akan menulis ke file nanti, masih mungkin bahwa Anda tidak akan dapat menulisnya. File mungkin telah pindah, izin mungkin telah berubah, dll. Dapat juga terjadi bahwa -wmendeteksi izin menulis tetapi beberapa faktor lain campur tangan untuk membuat file tidak dapat ditulisi .


1
Tentu saja! Saya seharusnya berpikir untuk memeriksa halaman manual tes. Terima kasih.
user50849

1
@ qweilun itu adalah shell builtin, tetapi Anda dapat menampilkan halaman manual melalui man testatauman [
chaos

5
@chaos Ini adalah shell builtin dan executable eksternal - cobatype -a
Volker Siegel

1
Per sumbertest kegunaan euidaccessyang hanya memeriksa izin bit . Apakah tidak ada faktor lain (mis. SELinux) yang dapat melarang akses tulis?
zamnuts

2
@ Brolow, &&dan ||memiliki prioritas yang sama. Mereka dievaluasi dari kiri ke kanan.
Wildcard

11

Pendekatan lain:

if >> /path/to/file
then
    echo "writeable"
else
    echo "write permission denied"
fi

Ini akan mencoba untuk membuka file untuk ditambahkan, dan, jika berhasil, jalankan tanpa perintah (yaitu, jalankan perintah null ) dengan output ke file. 

Hati-hati karena ini membuat file kosong jika tidak ada.

The -woperator dari testperintah hanya mungkin melakukan stat dan kemudian mencoba untuk mencari tahu apakah sepertinya Anda harus memiliki akses. Alternatif saya (di atas) lebih dapat diandalkan daripada testpendekatan dalam beberapa kondisi khusus, karena memaksa pemeriksaan akses dilakukan oleh kernel daripada shell. Sebagai contoh,

  • jika file berada pada sistem file non-Unix - terutama jika file tersebut dipasang dari server file non-Unix - karena statmungkin mengembalikan nilai mode yang menyesatkan.
  • jika file ada di sistem file yang di-mount read-only.
  • jika file memiliki ACL, dan mode membuatnya tampak seperti Anda harus memiliki akses, tetapi ACL menolaknya, atau sebaliknya.
  • jika beberapa kerangka kerja keamanan (AppArmor, SELinux, ...) menolak akses ke file.

3
Saya baru saja menguji ini (di Debian). Tidak ada waktu yang diubah, dan begitulah seharusnya bekerja pada Unix mana pun. Waktu akses harus diperbarui hanya jika Anda membaca dari file, waktu modifikasi harus diperbarui hanya jika Anda menulis ke file. Kode ini tidak melakukan keduanya. @ Schwern: apakah Anda memiliki referensi untuk pernyataan Anda? Adakah di antara kalian yang mencobanya?
G-Man Mengatakan 'Reinstate Monica'

2
PS @muru: Saya baru mencoba touchfile yang saya miliki tetapi tidak punya akses tulis, dan berhasil. Saya kira itu chmodfile dan chmoditu kembali. Jadi touchtampaknya sama sekali tidak berguna sebagai jawaban atas pertanyaan itu.
G-Man Mengatakan 'Reinstate Monica'

2
@ Ah-Ah, itu menarik. IIRC vimmemiliki perilaku mengubah izin dengan cepat ketika dipaksa untuk menulis pada file read-only. Aku memeriksa dengan strace, touch's opengagal dengan EACCES, tetapi panggilan berikutnya untuk utimensatberhasil, itulah sebabnya saya pikir touchsecara keseluruhan keluar berhasil.
muru

2
@uru: Terima kasih telah memeriksa itu. utimensat(2)mengatakan, " Persyaratan izin: 1. akses tulis (atau) 2. ID pengguna efektif penelepon harus cocok dengan pemilik file, ...."
G-Man Mengatakan 'Reinstate Monica'

3
Masalah lain seperti untuk Champignac: >> filetidak portabel (misalnya, menjalankan NULLCMD di zsh), gunakan true >> filesaja. Dan jika file tersebut bernama pipa, ia memiliki efek samping yang buruk.
Stéphane Chazelas

3

G-man benar: [ -w ]tidak akan selalu mengatakan yang sebenarnya. Di sini untuk mengatasi file yang tidak ada dan Izin pesan ditolak dari shell:

( [ -e /path/to/file ] && >> /path/to/file ) 2> /dev/null && 
  echo writable || 
  echo not writable

Pembaruan : Terlihat menakutkan, bukan? Ya, benar. Hmm ... bagaimana cara mengucapkannya ... JANGAN GUNAKAN INI, kecuali jika Anda benar-benar tahu Anda berada dalam kondisi yang diminta untuk bekerja seperti yang diharapkan. Lihat komentar Stephane.

Apa yang harus disimpulkan? Sekalipun [ -w ]tidak mengatakan yang sebenarnya, itu adalah satu perintah yang dimaksudkan untuk melakukan pekerjaan itu. Jika tidak, kami akan menyalahkannya, menulis laporan bug, dan itu akan berhasil di masa depan. Lebih baik memeriksa kondisi di mana ia bekerja dan digunakan [ -w ]; tulis kode khusus untuk kasus khusus. Penanganan masalah memiliki kondisi mereka sendiri.

[ -w /path/to/file ]

adalah yang terbaik a priori .


3
Jika file tersebut adalah pipa bernama, itu akan hang jika tidak ada baca, dan bahkan jika ada pembaca akan memiliki efek samping yang buruk. test -wdi sebagian besar implementasi penggunaan access(2)jadi harus cukup untuk menguji izin.
Stéphane Chazelas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.