Bagaimana saya bisa dengan aman mendapatkan versi ksh dari dalam script ksh?
Saya telah melihat solusi berikut :
ksh --version
echo ${.sh.version}
echo $KSH_VERSION
Dan mengingat keadaan yang tepat, masing-masing berfungsi dengan benar. Namun, saya peduli dengan kasus yang tidak sempurna.
Secara khusus, ada beberapa mesin yang bekerja dengan saya yang memiliki versi ksh yang lebih lama, yang untuk tujuan saya, sangat kurang fungsionalitasnya. Bagaimanapun, alasan saya ingin memeriksa versi (secara terprogram) adalah untuk melihat apakah versi ksh adalah salah satu versi yang kurang mampu; dan jika demikian, saya ingin menjalankan cabang dengan kode yang kurang bagus.
Namun, pada mesin yang bermasalah, ketidakmampuan shell meluas ke memeriksa versi ...
- Jika saya mencoba
ksh --version
, itu tidak mencetak apa-apa dan membuka contoh baruksh
! Jika saya mencoba
echo ${.sh.version}
,ksh
memperlakukan ini sebagai kesalahan sintaks yang tidak dapat diabaikan2> /dev/null
.$ echo ${.sh.version} 2> /dev/null ksh: ${.sh.version}: bad substitution
Tentu saja
echo $KSH_VERSION
tampaknya berfungsi dengan baik - maksud saya tidak akan crash - meskipun pada mesin ini kosong. Juga, saya melihat suatu tempat yangKSH_VERSION
hanya ditetapkan olehpdksh
.
Pertanyaan:
- Bagaimana saya bisa memeriksa versi
ksh
program dengan aman? Untuk tujuan saya di sini, saya tidak terlalu peduli apa nomor versi yang sebenarnya, hanya apakah itu versi lamaksh
. - Apakah
$KSH_VERSION
cukup baik? Maksud saya jika itu kosong, maka ituksh
versi yang sudah ketinggalan zaman? Apakah forum lain itu benar sehingga mungkin tidak disetel untuk versi yang lebih baruksh
? - Apakah tidak ada cara untuk memeriksa ini sama sekali?
sumber
PS1
untuk menggunakan fungsi ini. Namun, ksh Old tidak mendukung$()
dalamPS1
. Jadi jika ini adalah versi modern ksh, saya inginPS1
menggunakan fungsi yang saya buat; kalau itu versi lama, saya pakai saja$PWD
.Jawaban:
Saya pikir itu
.sh.version
sudah ada sejak versi pertama ATT ksh 93. Tidak tersedia dalam pdksh atau mksh. Karena${.sh.version}
ada kesalahan sintaksis dalam shell selain ksh93, bungkus tes untuk itu dalam subkulit dan lindungi di belakangeval
.KSH_VERSION
dimulai pada klon ksh domain publik (pdksh), dan ditambahkan ke shell Korn yang sebenarnya baru-baru ini, pada tahun 2008 dengan ksh93t.Alih-alih menguji nomor versi, Anda harus menguji fitur tertentu yang membuat Anda sedih. Sebagian besar fitur dapat diuji dengan mencoba beberapa konstruk dalam sebuah subkulit dan melihat apakah itu memicu kesalahan.
sumber
${.sh.version}
sebagai kesalahan sintaks yang tidak dapat direkonsiliasi. Pesan yang saya dapatkan adalahbad substitution
./dev/null
dan abaikan status keluar.eval '_sh_version=$(echo "${.sh.version}")' 2>/dev/null
bekerja lebih baik?KSH_VERSION
tidak diimplementasikanksh93
sebelum versi 93t. Ini akan diatur dalammksh
,pdksh
,lksh
. Jadi untuk memeriksa versiksh
, kita dapat mencoba langkah-langkah ini:KSH_VERSION
untuk mendeteksimksh
,pdksh
,lksh
ksh93
danksh88/86
( Biarkan David Korn tunjukkan kepada kami ).Dengan ini dalam pikiran, saya akan pergi dengan:
sumber
$KSH_VERSION
tidak kosong dulu? Di mesin Ubuntu saya, ini mencetak "ksh93", belumKSH_VERSION
diatur..kshrc
.ENV
variabel disetel (dan biasanya disetel ke~/.kshrc
), skrip pasti akan membaca.kshrc
file. Tentu saja, itu akan sangat aneh untuk sebuah skrip untuk menetapkan KSH_VERSION palsu tetapi ini tetap mungkin, seperti mengeksekusi skrip secara eksplisit dengan penerjemah yang berbeda dari yang ditentukan pada baris pertama adalah situasi yang memungkinkan.KSH_VERSION
. Dan dimksh
,pdksh
,lksh
,KSH_VERSION
ditandai sebagai dibaca.Untuk
ksh
rilis "nyata" (yaitu berbasis AT&T), saya menggunakan perintah ini:Berikut adalah berbagai hasil yang saya dapatkan:
Ksh asli:
dtksh;
Ksh93 modern:
Untuk
pdksh
/msh
ksh
klon danksh
versi AT&T modern juga, ini adalah sesuatu yang berfungsi:Edit:
Saya mengabaikan Anda bertanya tentang melakukannya dari dalam skrip, bukan dengan mengetahui jalan ke biner ksh diuji.
Dengan asumsi Anda benar-benar menginginkan versi yang
ksh
digunakan, dan bukan fitur yang didukungnya, berikut adalah salah satu cara untuk melakukannya hanya dengan menggunakanstrings
perintah yang seharusnya berfungsi setidaknya di Linux dan Solaris:Perhatikan bahwa metode ini tidak dapat diandalkan karena
/proc
mungkin tidak dipasang, dan tentu saja ada kelemahan lainnya. Ini belum teruji pada OS Unix lainnya.sumber
lksh
danpdksh
di Debian Jessie.lksh
danpdksh
tidak dapat disortir dari merekaKSH_VERSION
?strings
pada mereka.KSH_VERSION
pasti bisa.ksh
rilis " nyata " », saya secara eksplisit mengecualikan klon ksh non AT&T sepertipdksh
,mksh
danlksh
.strings
beberapa binary ksh adalah ide yang buruk karena Anda tidak tahu apakah itu yang menjalankan skrip Anda. Mungkin naskah Anda sedang dijalankan oleh/usr/local/bin/ksh
atau/home/bob/bin/ksh
atau/bin/sh
atau/usr/posix/bin/sh
atau ...Ketika saya sedang menulis skrip
ksh
, saya perhatikan bahwa-a
opsiwhence
perintah built-in ksh tampaknya tidak didukung di versi yang lebih lamaksh
. Dan ini tampaknya benar pada semua sistem yang saya periksa, termasuk Solaris, AIX, HP-UX, dan Linux.Jadi, inilah solusinya sebagai fungsi ksh:
Dan inilah cara menggunakannya:
sumber
${.sh.version}
?whence
di Zsh memiliki-a
whence
yang tidak terikat dengan ksh atau versi daripadanya. Saya bahkan tidak tahu mengapa Anda ingin memeriksa apakah ksh adalah versi lama dari instance zsh, yang merupakan shell yang sama sekali berbeda./bin/ksh
, mis. Di Debian Linux. Sekarang saya tidak menggunakannya di sana (dan saat ini saya tidak dapat mengganti shell login saya untuk memeriksa), jadi saya tidak tahu apakah itu membaca.kshrc
atau tidak, tetapi saya menduga itu akan terjadi.CTRL+ ALT+V
atau
ESC, CTRL+V
Biasanya terbukti sangat andal sejauh menentukan secara interaktif versi KSH yang Anda gunakan, namun menulisnya terbukti lebih sulit.
sumber
set -o vi
untuk mengatur keybindings menjadi vi-like. Sebelum itu, atau dengan + o vi atau -o emacs, itu tidak akan menunjukkan kepada saya. PD KSH v5.2.14 99/07 / 13.2 di openbsd 6.1Saya pikir masalah mendasar dengan menggunakan $ {. Sh.version} adalah bahwa ksh88 berhenti, dengan kode keluar yang tidak nol.
Jadi solusi saya adalah dengan meletakkan kode yang mereferensikan $ {. Sh.version} dalam sub-shell, kemudian tes untuk melihat apakah sub-shell keluar non-nol dan memiliki kode dalam sub-shell yang akan bekerja pada versi ksh tempat referensi $ {. sh.version} berfungsi. Membungkusnya menjadi fungsi yang kemudian dipanggil oleh fungsi lain yang membalikkan kode kembali, sehingga panggilan terakhir memeriksa true.
Saya telah menjalankan ini pada AIX dan Oracle Enterprise Linux 5 & 6, dengan ksh88, ksh93 dan pdksh.
Pete
sumber
.sh.version
(memangKSH_VERSION
efektif alias untuk itu). Juga beberapa shell, misalnya NetBSD sh, cukup berhenti membaca setelah bertemu${.sh.version}
dan tidak ada jumlah pengalihan yang dapat membuat mereka menjalankan skrip.Berikut ini tampaknya bekerja dengan cukup baik untuk semua cangkang yang telah saya uji, termasuk ksh88e lama dan berbagai klon Ksh umum yang hampir lengkap (meskipun masing-masing hanya satu versi), meskipun saya belum menguji cangkang Bourne asli yang sebenarnya ( dan melakukannya mungkin memerlukan mengadaptasi
test
ekspresi untuk versi yang lebih lama ....Tambahan:
Saya sekarang juga berhasil menguji ini dengan Heirloom Bourne Shell, meskipun dengan program eksternal (dan lebih modern)
test
.sumber
${.sh.version}
tidak dapat menjadi bagian dari solusi karena versi tertentu dari ksh - versi yang menjadi perhatian postingan asli - mengalami kesalahan fatal pada sintaksis itu.