bash: Beberapa masalah saat menggunakan read <<< “$ VARIABLE” pada partisi root read-only. Adakah solusi yang diketahui?


11

Hanya secara kebetulan saya harus menggunakan skrip ATA-ID-to-device-name saya (ditemukan di sini: /server/244944/linux-ata-errors-translating-to-a-device-name/ 426561 # 426561 ) pada partisi read-only / . Jika Anda penasaran, itu adalah konsol pemulihan Ubuntu yang akan memungkinkan Anda mengakses /partisi Anda , tetapi akan me-mountnya hanya-baca secara default. Saya senang tentang itu, karena kalau tidak saya mungkin tidak akan pernah menemukan bahwa skrip saya berperilaku aneh pada sistem R / O karena garis tertentu, ini:

IFS=: read HostMain HostMid HostSub <<< "$HostFull"

Ini tidak berfungsi jika tidak ada izin tertulis. Tapi saya tidak akan mengira itu akan gagal. Namun ternyata <<<operator memang perlu menulis beberapa file sementara ke suatu tempat.

Tetapi apakah ada cara untuk menghindari pembuatan file sementara, atau, apakah ada cara untuk menentukan di mana file itu ditulis? Di konsol pemulihan Ubuntu, ada --- anehnya --- menulis izin pada /rundirektori, jadi itu bisa dilakukan, jika saya bisa "menyuruh" readuntuk menulis file temp ke tempat lain daripada biasanya.


2
@ gniourf_gniourf Tidak, "membuka deskriptor file" tidak akan menjadi masalah (mengapa?), dan /dev/fdtidak ada hubungannya dengan ini. <<<adalah pelakunya, karena itu membuat file sementara (yang perlu ditulis di suatu tempat).
Gilles 'SANGAT berhenti menjadi jahat'

Jawaban:


8

Array dapat membuat string parsing tanpa perlu file temporal. Jangan lupa mematikan globbing.

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f

2
atau bahkan tanpa IFS, jika Anda yakin tidak ada spasi di $HostFullsebagai begitu: Hosts=( ${HostFull//:/ } ). Atau bahkan jika ada spasi: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(atau yang serupa, saya jadi bingung :D).
gniourf_gniourf

Anda benar, karena Anda menunjukkan ekspansi parameter adalah bisnis yang rumit ...
xae

4

Saya setuju dengan @gniourf_gniourf, Anda mungkin memerlukan akses tulis tetapi tidak ke deskriptor file, kemungkinan besar file.

Anda dapat menguji ini dengan melacak eksekusi perintah Anda saat berada di partisi readonly.

{ strace -p "$$" & sleep 1; read var1 <<< "hi"; sleep 1; kill "$1"; }

Di atas akan berjalan stracepada Bash shell (proses $$). Kemudian tidur selama 1 detik, dan kemudian menjalankan readdari SINI STRING. Saya sudah meletakkan string "hi"di posisi ini. Saya kemudian sleepuntuk satu detik dan kemudian killyang strace.

Contoh

Saat mem-parsing output ini Anda akan melihat bahwa file dibuka sebagai O_WRONLY, yang untuk menulis ke file.

open("/tmp/sh-thd-4137571604", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3

Di atas kita dapat melihat file apa yang sedang ditulis oleh urutan perintah Anda.


1
Tidak untuk "membuat file deskriptor" (itu tidak masuk akal). Untuk membuat file . Bukannya readmembuka file untuk menulis (itu akan konyol), itu <<<.
Gilles 'SANGAT berhenti menjadi jahat'

@Gilles - terima kasih, saya tidak mengerti apa yang dikatakannya kepada saya. Membersihkan A.
slm

Terima kasih banyak! Teknik yang sangat bagus, yang bahkan mungkin bisa membantu saya beberapa kali di masa depan dengan masalah serupa. Namun, satu hal yang membuat saya khawatir, dan itu adalah fakta bahwa /tmpini adalah jalur yang sulit dikodekan . Dan mungkin Anda sudah menebaknya, /tmp IS sana sudah, tetapi hanya-baca juga! Dan karena bekerja pada konsol pemulihan akan membuat saya masuk ke sistem file langsung saya , saya tidak ingin mengacaukan di sana dengan symlinking atau apa pun (tidak bahkan saat di konsol itu).
syntaxerror

3

Saya menemukan parameter posisi sangat berguna untuk tugas semacam ini. Ini umumnya portabel untuk semua shell juga, dan tidak ada biaya garpu atau file sementara.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub

Pendekatan yang bagus! Terima kasih. Plus, saya suka itu tidak memerlukan alat eksternal (bahwa kita biasanya tidak diharapkan untuk menemukan di lingkungan yang terbatas bagaimanapun). Satu-satunya hal yang dapat menyebabkan beberapa masalah adalah $1, $2, $3hal: ingat bahwa dalam naskah, ini biasanya akan berdiri untuk argumen dilewatkan ke script itu sendiri . - Dan sementara kita berada di dalamnya: jika IFS dimaksudkan sebagai spasi, * IFS = * tidak akan melakukan dalam sintaks ini; Anda harus menentukan IFS = '' secara eksplisit.
syntaxerror
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.