Saya perlu membuat file konfigurasi untuk skrip saya sendiri: di sini sebuah contoh:
naskah:
#!/bin/bash
source /home/myuser/test/config
echo "Name=$nam" >&2
echo "Surname=$sur" >&2
Isi dari /home/myuser/test/config
:
nam="Mark"
sur="Brown"
itu berhasil!
Pertanyaan saya: apakah ini cara yang benar untuk melakukan ini atau ada cara lain?
bash
shell
shell-script
Pol Hallen
sumber
sumber
abcde
juga melakukannya dengan cara ini dan itu adalah program yang cukup besar (untuk skrip shell). Anda dapat melihatnya di sini .Jawaban:
source
tidak aman karena akan mengeksekusi kode arbitrer. Ini mungkin bukan masalah bagi Anda, tetapi jika izin file tidak benar, mungkin bagi penyerang dengan akses sistem file untuk mengeksekusi kode sebagai pengguna istimewa dengan menyuntikkan kode ke file konfigurasi yang dimuat oleh skrip yang diamankan seperti skrip yang diamankan seperti skrip skrip init.Sejauh ini, solusi terbaik yang dapat saya identifikasi adalah solusi reinventing-the-wheel yang canggung:
myscript.conf
Menggunakan
source
, ini akan berjalanecho rm -rf /
dua kali, serta mengubah pengguna yang berjalan$PROMPT_COMMAND
. Sebaliknya, lakukan ini:myscript.sh (Bash 4)
myscript.sh (kompatibel Mac / Bash 3)
Harap balas jika Anda menemukan exploit keamanan dalam kode saya.
sumber
*
input dengan benar, tapi lalu apa yang di Bash menangani karakter itu dengan baik?my\\password
Ini adalah versi yang bersih dan portabel yang kompatibel dengan Bash 3 dan yang lebih baru, di Mac dan Linux.
Ini menentukan semua default di file terpisah, untuk menghindari kebutuhan akan fungsi konfigurasi "default" yang sangat besar, berantakan, duplikat di semua skrip shell Anda. Dan itu memungkinkan Anda memilih antara membaca dengan atau tanpa fallback default:
config.cfg :
config.cfg.defaults :
config.shlib (ini adalah perpustakaan, jadi tidak ada shebang-line):
test.sh (atau skrip mana pun yang ingin Anda baca nilai konfigurasi) :
Penjelasan naskah tes:
printf
garis itu? Ya, itu sesuatu yang harus Anda waspadai:echo
adalah perintah buruk untuk mencetak teks yang tidak dapat Anda kendalikan. Bahkan jika Anda menggunakan tanda kutip ganda, itu akan menafsirkan bendera. Coba aturmyvar
(dalamconfig.cfg
) ke-e
dan Anda akan melihat baris kosong, karenaecho
akan berpikir bahwa itu adalah bendera. Tetapiprintf
tidak memiliki masalah itu. Theprintf --
mengatakan "mencetak ini, dan tidak menafsirkan sesuatu sebagai bendera", dan"%s\n"
mengatakan "memformat output sebagai string dengan baris baru Trailing, dan terakhir parameter akhir adalah nilai untuk printf ke format.myvar="$(config_get myvar)";
. Jika Anda akan mencetaknya di layar, saya sarankan menggunakan printf agar benar-benar aman terhadap string yang tidak kompatibel dengan gema yang mungkin ada di konfigurasi pengguna. Tapi gema baik-baik saja jika variabel yang disediakan pengguna bukan karakter pertama dari string yang Anda gema, karena itulah satu-satunya situasi di mana "bendera" dapat ditafsirkan, jadi sesuatu sepertiecho "foo: $(config_get myvar)";
aman, karena "foo" tidak mulai dengan tanda hubung dan oleh karena itu memberi tahu gema bahwa sisa string juga bukan flag untuk itu. :-)sumber
config.cfg.defaults
sebagai pengganti mendefinisikan mereka pada saat menelepon$(config_get var_name "default_value")
. tritarget.org/static/…Parsing file konfigurasi, jangan jalankan.
Saat ini saya sedang menulis aplikasi di tempat kerja yang menggunakan konfigurasi XML yang sangat sederhana:
Dalam skrip shell ("aplikasi"), inilah yang saya lakukan untuk mendapatkan nama pengguna (kurang lebih, saya telah memasukkannya ke dalam fungsi shell):
The
xml
perintah XMLStarlet , yang tersedia untuk sebagian besar mesin-mesin Unix.Saya menggunakan XML karena bagian lain dari aplikasi juga berkaitan dengan data yang dikodekan dalam file XML, jadi itu paling mudah.
Jika Anda lebih suka JSON, ada
jq
yang mudah digunakan shell JSON parser.File konfigurasi saya akan terlihat seperti ini di JSON:
Dan kemudian saya akan mendapatkan nama pengguna dalam skrip:
sumber
eval
untuk menetapkan beberapa nilai maka Anda mengeksekusi bagian yang dipilih dari file konfigurasi :-).eval
apa - apa. Hit kinerja menggunakan format standar dengan parser yang ada (meskipun itu utilitas eksternal) dapat diabaikan dibandingkan dengan kekokohan, jumlah kode, kemudahan penggunaan, dan pemeliharaan.Cara yang paling umum, efisien dan benar adalah dengan menggunakan
source
, atau.
sebagai bentuk singkatan. Sebagai contoh:atau
Namun, yang perlu dipertimbangkan adalah masalah keamanan yang dapat ditimbulkan oleh file konfigurasi eksternal yang bersumber eksternal, mengingat kode tambahan dapat dimasukkan. Untuk informasi lebih lanjut, termasuk tentang cara mendeteksi dan menyelesaikan masalah ini, saya akan merekomendasikan untuk melihat bagian 'Amankan' di http://wiki.bash-hackers.org/howto/conffile#secure_it
sumber
Saya menggunakan ini dalam skrip saya:
Harus mendukung setiap kombinasi karakter, kecuali kunci yang tidak boleh ada
=
di dalamnya, karena itulah pemisahnya. Ada lagi yang berhasil.Juga, ini sepenuhnya aman karena tidak menggunakan
source
/eval
sumber
Untuk skenario saya,
source
atau.
baik-baik saja, tetapi saya ingin mendukung variabel lingkungan lokal (yaitu,FOO=bar myscript.sh
) diutamakan daripada variabel yang dikonfigurasi. Saya juga ingin agar file konfigurasi dapat diedit pengguna dan nyaman bagi seseorang yang menggunakan sumber file konfigurasi, dan menjaganya agar tetap sekecil / sesederhana mungkin, agar tidak mengalihkan perhatian dari tekanan utama skrip saya yang sangat kecil.Inilah yang saya pikirkan:
Pada dasarnya - ini memeriksa definisi variabel (tanpa menjadi sangat fleksibel tentang spasi putih) dan menulis ulang garis-garis sehingga nilai dikonversi ke default untuk variabel itu, dan variabel tidak dimodifikasi jika ditemukan, seperti
XDG_CONFIG_HOME
variabel di atas. Sumber ini mengubah versi file konfigurasi ini dan melanjutkan.Pekerjaan di masa depan dapat membuat
sed
skrip lebih kuat, memfilter baris yang terlihat aneh atau tidak definisi, dll, tidak merusak komentar akhir baris - tetapi ini cukup baik untuk saya saat ini.sumber
Ini singkat dan aman:
The
-i
Memastikan Anda hanya mendapatkan variabel daricommon.vars
sumber
Kamu bisa melakukannya:
sumber