Saya sedang menulis skrip shell yang seharusnya agak aman yaitu tidak melewatkan data aman melalui parameter perintah dan sebaiknya tidak menggunakan file sementara. Bagaimana saya bisa melewatkan variabel ke stdin dari sebuah perintah? Atau, jika tidak memungkinkan, bagaimana cara menggunakan file sementara dengan benar untuk tugas tersebut?
105
$PATH
? Sehinggacat
dapat diganti menjadi/bin/cat "$@" | tee /attacker/can/read/this/file
Jawaban:
Sesuatu yang sederhana seperti:
sumber
echo "$blah"
lebih baik.blah=-n
,blah=-e
... gunakanprintf
sebagai gantinya. unix.stackexchange.com/questions/65803/…printf '%s\n' "$blah"
? Dengan satu perubahan itu (menghindari banyak jebakan dalamecho
spesifikasi, yang merupakan jawaban luar biasa Stephane yang menjelaskan secara rinci di Why isprintf
better thanecho
? Di Unix & Linux , atau bagian PENGGUNAAN APLIKASI dariecho
spesifikasi yang menyentuh lebih singkat) itu sempurna jawaban yang masuk akal.Meneruskan nilai ke
stdin
dalam bash sesederhana:Selalu pastikan Anda memberi tanda kutip di sekitar ekspresi variabel!
sumber
<<<
tidak dijamin akan tersedia, sejauh yang saya tahu, mereka tidak ada di basis POSIX. Mereka akan bekerja seperti yang diharapkan, selama Anda hanya menjalankannyabash
. Saya hanya menyebutkannya, karena mereka OP mengatakan 'shell' bukan secara spesifik 'bash'. Meskipun dia menandai pertanyaan itu denganbash
... jadi ini jelas merupakan jawaban yang dapat diterima.echo
metode ini karena pembuatan pipa. Perintah herestring akan diproses sepenuhnya olehbash
, meskipun dalam situasi ini (seperti yang disebutkan) Anda sebaiknya tahu bahwa perintah tersebut akan berfungsi pada bash Anda, jika tidak, pesan kesalahan yang dihasilkan karena tidak mendukung herestring juga akan membocorkan informasi tersebut.echo
adalah built-in. Tidak ada pipa di sana, bukan? Ini Unix, tapi tidak mungkin Unix sebanyak itu .printf '%s\n' "$var"
memberikan hasil yang samaecho "$var"
tetapi tidak akan rusak jika, misalnyavar=-en
, dan bahkan tidak memerlukan bash.Perhatikan bahwa '
echo "$var" | command
operasi berarti bahwa input standar terbatas pada baris yang digaungkan. Jika Anda juga ingin terminal terhubung, Anda harus lebih menarik:Ini berarti bahwa baris pertama akan menjadi isinya
$var
tetapi sisanya akan datang daricat
pembacaan input standarnya. Jika perintah tidak melakukan sesuatu yang terlalu mewah (coba aktifkan pengeditan baris perintah, atau jalankan sepertivim
itu) maka itu akan baik-baik saja. Jika tidak, Anda harus benar-benar mewah - saya pikirexpect
atau salah satu turunannya kemungkinan besar akan sesuai.Notasi baris perintah secara praktis identik - tetapi titik koma kedua diperlukan dengan tanda kurung sedangkan tidak dengan tanda kurung.
sumber
( echo "$LIST"; cat - ) | sed 1q
ini berfungsi untuk saya tetapi saya perlu menekan ctrl d ketika saya menjalankan skrip ini?cat -
terus membaca dari keyboard sampai EOF atau interupsi, jadi Anda perlu memberitahukannya EOF dengan mengetikkan control-D.cat
sama sekali jika Anda tidak menginginkan input terminal, seperti pada baris pertama. Atau Anda dapat menggunakancat
untuk membuat daftar file. Atau ... Jika Anda ingin perintah membaca input terminal, Anda harus memberitahukannya ketika telah mencapai akhir input. Atau Anda bisa menggunakan( echo "$var"; sed /quit/q - ) | command
; ini berlanjut sampai Anda mengetik baris yang berisi 'keluar'. Anda bisa menjadi inventif tanpa akhir dengan cara Anda menanganinya. Waspadai legenda urban lama dari sebuah program yang berhenti bekerja ketika pengguna mulai bekerja dengan Ekuador. Mereka akan mengetik nama ibu kotanya, Quito, dan program keluar.echo "$LIST" | sed 1q | ...
? Itu semua tergantung pada Anda. The<<EOF
notasi harus memerlukan EOF pada awal garis di suatu tempat sendiri ke bawah file. Saya tidak akan menggunakannya, saya pikir - tetapi saya masih tidak yakin apa yang ingin Anda capai. Sederhanaecho "$LIST" | command
atauecho $LIST | command
mungkin akan cukup dalam praktiknya (dan penting bagi Anda untuk mengetahui pentingnya perbedaan di antara keduanya).Saya menyukai jawaban Martin, tetapi memiliki beberapa masalah tergantung pada apa yang ada di variabel. Ini
lebih baik jika variabel Anda berisi "atau!
sumber
foo1=-; foo2='"'; foo3=\!; cat<<<"$foo1"; cat<<<"$foo2"; cat<<<"$foo3"
berfungsi dengan baik untuk saya. Apa sebenarnya yang dilakukan ketiganya"
? AFAIK Anda hanya melakukan prepending dan menambahkan string kosong.Ini
cat
tidak benar-benar diperlukan, tetapi membantu menyusun kode dengan lebih baik dan memungkinkan Anda untuk menggunakan lebih banyak perintah dalam tanda kurung sebagai masukan untuk perintah Anda.sumber
$passwd
Sesuai jawaban Martin, ada fitur bash bernama Here Strings (yang merupakan varian dari fitur Dokumen Di Sini yang lebih banyak didukung ).
http://www.gnu.org/software/bash/manual/bashref.html#Here-Strings
Perhatikan bahwa Di Sini Strings tampaknya hanya bash, jadi, untuk meningkatkan portabilitas, Anda mungkin akan lebih baik dengan fitur Dokumen Sini asli, sesuai jawaban PoltoS:
Atau, varian yang lebih sederhana dari yang di atas:
Anda dapat menghilangkan
(
dan)
, kecuali jika Anda ingin ini dialihkan lebih jauh ke perintah lain.sumber
Cara yang kuat dan portabel ini telah muncul di komentar. Ini harus menjadi jawaban yang berdiri sendiri.
atau
Catatan:
echo
, alasannya ada di sini: Mengapaprintf
lebih baik dariecho
?printf "$var"
salah. Argumen pertama adalah format yang mana berbagai urutan suka%s
atau\n
yang ditafsirkan . Untuk meneruskan variabel ke kanan, itu tidak harus diartikan sebagai format.Biasanya variabel tidak mengandung baris baru. Perintah sebelumnya (dengan
%s
) meneruskan variabel apa adanya. Namun alat yang bekerja dengan teks mungkin mengabaikan atau mengeluh tentang baris yang tidak lengkap (lihat Mengapa file teks diakhiri dengan baris baru? ). Jadi Anda mungkin menginginkan perintah terakhir (dengan%s\n
) yang menambahkan karakter baris baru ke konten variabel. Fakta yang tidak jelas:<<<"$var" my_cmd
) menambahkan baris baru.my_cmd
, meskipun variabelnya kosong atau tidak ditentukan.sumber
Coba ini:
sumber
ps -u
saat echo dijalankan?echo
adalah built-in, jadi tidak ada proses untuk ditampilkan di psecho "$variable"
lebih baik.Kerjakan saja:
Jika var tidak mengandung spasi maka tanda kutip dapat dihilangkan.
Jika menggunakan bash, Anda juga dapat melakukan:
Hindari menggunakan echo tanpa -n karena akan menyalurkan vraiable dengan linebreak tambahan di akhir.
sumber
%s
, printf tidak akan mencetak apa pun.my_var="%s"; printf "$my_var";
- mungkin mencobaprintf "%s" "$my_var" | my_cmd
?