Saya mencari cara yang sederhana dan dapat diandalkan untuk mendapatkan nama shell saat ini dari dalam skrip atau file sumber ( bukan dari baris perintah). Saya diharapkan hanya melakukannya $(basename "$SHELL")
tetapi jika shell login saya zsh
dan saya memiliki kode berikut di some_script.sh
this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
dan saya menjalankannya dengan bash some_script.sh
, itu masih daftar zsh
bukannya bash
penerjemah yang digunakan /bin/bash
. Saya tidak yakin mengapa perancang shell memilih untuk menampilkan shell default alih-alih shell saat ini, tapi sepertinya itulah yang kami lakukan.
Ada beberapa pertanyaan lain yang agak mirip (di sini dan di sini ), tetapi jawaban mereka gagal dalam banyak hal.
- Mereka sering menganggap pengguna sedang mencoba mencari tahu shell interaktif apa yang saat ini mereka gunakan, tetapi itu gila. Aku tahu apa shell saya perintah mengetik ke - Saya perlu kode yang dapat dijalankan di mana saja untuk dapat menentukan apa shell itu menggunakan.
- Mereka sering memberikan beberapa hal berbeda untuk dicoba - lagi seolah-olah Anda berada di baris perintah dan hanya bisa bermain-main sampai Anda mengetahui Anda menggunakan bash - tetapi saya membutuhkan satu hal yang dapat diandalkan dalam semua konteks.
- Mereka sering memberikan hal-hal yang sama sekali tidak berguna dari skrip, seperti
echo $0
. Itu gagal seperti yang ditunjukkan dalam skrip di atas. (Ya itu bekerja di baris perintah shell interaktif, tapi mengapa Anda tidak pernah tahu shell apa yang Anda gunakan?) - Mereka kadang-kadang memberikan perintah yang (dalam tes terbatas saya) termasuk informasi yang benar, seperti
ps -p $$
, tetapi tidak memiliki platform silang, sed-awk kompatibel lintas-shell perintah untuk pipa melalui untuk mendapatkan hanya nama shell dan mengabaikan informasi lain yang datang bersama untuk perjalanan. - Mereka termasuk hal-hal yang hanya akan bekerja pada beberapa cangkang, seperti
$BASH_VERSION
dan$ZSH_VERSION
. Saya ingin mendukung banyak kerang mungkin, sepertifish
,csh
,tcsh
.
Bagaimana cara andal dan akurat mendeteksi setiap saat shell? Saya mencari sesuatu yang akan bekerja di seluruh platform, dalam skrip, dan sebanyak mungkin kerang dan masuk akal 1 .
UPDATE : Ketika saya memposting pertanyaan ini saya berharap bahwa ada beberapa fasilitas dibangun ke shell untuk memberi kami info ini, yang tampaknya tidak demikian. Karena sekarang tampaknya tak terhindarkan untuk mengandalkan sesuatu di luar cangkang, saya harus membuat lebih eksplisit bahwa saya memintasolusi lintas platform (yang, meskipun tersirat oleh keberatan saya terhadap jawaban lain di atas, mungkin mudah terlewatkan jika Anda tidak membaca pertanyaan dengan cermat).
Pembaruan 2 Jika ada yang masih percaya ini adalah duplikat dari pertanyaan khusus Linux karena jawaban Stéphane bukan hanya untuk Linux, berikut adalah perbedaan antara apa yang saya minta dan apa yang dia sediakan. (Perhatikan bahwa apa yang ditulisnya cerdik, dan saya tidak mengetuknya, tetapi itu tidak menyelesaikan masalah saya.)
- Saya mencari sesuatu yang sederhana dan handal , yang
- dapat ditambahkan ke skrip atau definisi fungsi apa pun (yang akan bersumber dari
.zshrc
atau.bash_profile
atau apa pun) ke cabang. - Anda tidak dapat menggunakan skripnya sebagai utilitas luar yang meneruskan nama juru bahasa ke skrip panggilan / fungsi, karena itu akan selalu ditafsirkan oleh penerjemah default dan mengembalikannya. Ini membuatnya sulit atau tidak mungkin digunakan untuk tujuan saya. Jika memungkinkan, itu masih sangat sangat sulit, dan solusi untuk membuatnya berfungsi tidak diberikan dalam jawabannya. Karena itu dia tidak menjawab pertanyaan saya, oleh karena itu itu bukan duplikat.
Jika Anda ingin melihat sesuatu yang akan bekerja, lihatlah ShellDetective di GitHub . Itu mungkin membuatnya lebih mudah untuk melihat perbedaan antara apa yang sudah ada pada SE, dan apa yang dicari oleh pertanyaan ini (dan sebenarnya ditulis untuk memenuhi kebutuhan pertanyaan ini, yang tidak terpenuhi di tempat lain).
(PS jika Anda tidak percaya ada use case untuk ini, bayangkan fungsi yang bersumber ke .zshrc
,, .bash_profile
atau .profile
tergantung pada server apa yang sedang digunakan dan apa shell yang telah tersedia. Mereka bersumber sehingga mereka tidak memiliki garis shebang. Mereka paling berguna jika mereka dapat bekerja di shell apa pun, tetapi kadang-kadang mereka harus tahu shell mana yang mereka miliki untuk mengetahui bagaimana harus bersikap.)
1 Saya tidak peduli dengan "kerang" yang bukan kerang dalam arti kata tradisional. Saya tidak peduli dengan beberapa shell yang ditulis oleh seorang pria untuk dirinya sendiri. Saya hanya peduli dengan shell nyata yang benar-benar terjadi di alam liar, dan yang seseorang mungkin harus menggunakan ketika masuk ke beberapa server di mana mereka tidak bisa hanya menginstal shell apa pun yang mereka inginkan.
sh -c "…"
, dan kemudian lakukan sebagian besar pekerjaan di sintaks shell POSIX.fish
dan gunakan untuk menjalankan skrip Anda, apakah Anda maufish
ataucsh
?Jawaban:
Saya mendapatkan hasil yang luar biasa dengan kombinasi ini:
Pada Tru64 (OSF / 1), output memiliki tanda kurung di sekitar shell. Tack on
tr -d '()'
untuk menghapusnya.Tampaknya berfungsi pada semua shell, pada Solaris 10 dan RHEL 5.7 / 6.4. Tidak menguji distro lain seperti Debian, Ubuntu, atau Mint, tapi saya pikir mereka semua harus bekerja sama; Saya juga tidak tahu apakah FreeBSD akan berfungsi.
sumber
Jadi saya masih mencoba untuk menyempurnakan ini, tapi saya pikir saya punya ide yang akan berhasil. Seperti yang telah Anda perhatikan, apa yang Anda coba lakukan adalah jika bukan tidak mungkin, sangat sulit dilakukan di semua shell (setiap varian yang Anda tambahkan ke polyglot meningkatkan kerumitan pada tingkat yang lebih besar daripada linear). Anda mungkin dapat melakukannya jika Anda membagi menjadi Bourne (sh, ash, dash, bash, ksh, pdksh, zsh, dll.) dan c style shells (csh, tcsh, ikan, dll.) tetapi variasi antar
csh
varian menyajikan berbagai hal menarik tantangan.Jadi mari kita menipu dan menulis deteksi rutin kita dalam bahasa yang dikenal (bash dengan garis shebang, C, perl, python, apa pun) dan tentukan nama executable dari induknya. kita kemudian dapat menggunakan dua trik untuk mendapatkan informasi kembali ke induk, yaitu nilai pengembalian (s) dan satu kata ditulis ke standar keluar. Pada shell yang diturunkan, kita akan mengembalikan 0 dan menulis nama shell karena semuanya memiliki penanganan backtick yang baik. pada kelompok kerang C kita bisa mulai menambahkan nilai kembali untuk setiap set ketidakcocokan yang perlu kita selesaikan. Nilai pengembalian lebih dari dua ratus akan menunjukkan kesalahan dimulai dengan semuanya tampak baik-baik saja, tetapi saya tidak bisa mengatakan siapa orang tua saya di dua ratus.
Program dalam sepertinya mudah di linux (
/proc/ppid/exe
setengah dari pertempuran). Saya cukup yakin ini dapat dilakukan pada bsd dengan opsi ps, tetapi saya tidak memiliki sistem bsd yang berjalan saat ini untuk mengujinya, dan mac saya memerlukan hard drive baru (dan hanya 10,4 saja). Meskipun ini mengurangi masalah sintaksis shell secara signifikan, ia memperkenalkan serangkaian masalah kompatibilitas yang berbeda. Saya masih berpikir itu memiliki kemungkinan.sumber
sh -c "..."
, yang diambilnya dari pertanyaan lain . (Maaf: Saya melewatkan jawaban Anda pada awalnya karena saya tidak melihat kode di dalamnya, dan hanya kembali dan membacanya nanti.)case $shell in sh)...
(itu sintaks Bourne-only), atauswitch ($shell)
(csh-only).test "$shell" = "sh" && do-something
bekerja dicsh
/sh
/rc
/es
, tapi tidakfish
.../dev/null
. Tapi saya punya solusi, yang akan saya posting setelah semuanya berhasil.coba sesuatu seperti ini
sumber
csh
dantcsh
.fish
, tapi kemudian hanya dalamfish
, sayangnya:ps h -p %self -o args='' | cut -f1 -d' '
. Ini menciptakan masalah ayam dan telur ... Anda harus tahu Anda berada difish
dalam untuk mengeksekusifish
versi kode ...set shell_bin=`ps -p $$ -o args='' | cut -f1 -d' '`
- akan bekerja dengan CSH tetapi tidak yang laincsh
/tcsh
, itu adalah bagian ini:ps -p $$ -o args='' | cut -f1 -d' '
, yang kembali-sh
padacsh
, dan-csh
ditcsh
.Saya percaya Anda tidak dapat selalu mendapatkan nama shell saat ini , dan saya pikir Anda harus menyadari keterbatasan apa yang mungkin terjadi.
Pada distribusi Linux, sebagian besar pengguna akan memiliki
bash
login & shell interaktif mereka (karenabash
shell default pada kebanyakan distro). Beberapa pengguna akan mengatur shell mereka kezsh
,csh
(dan varian) atau kefish
.(Sebagai komentar dan jawaban lainnya menjelaskan, menemukan andal shell dari
bash
,zsh
,tcsh
,fish
sudah menantang)Namun beberapa pengguna yang aneh dapat menetapkan shell login mereka untuk sesuatu yang sama sekali berbeda - juru Lisp,
scsh
,es
, beberapa bahasa scripting à la Python, atau Ocaml, atau Perl, dll ...- dan itu adalah kebebasan mereka untuk melakukannya. Mungkin, beberapa orang mengkode shell mereka sendiri dan menggunakannya secara interaktif. Bahkan jika Anda menemukan shell aneh mereka, Anda tidak akan dapat melakukan sesuatu yang berguna darinya (maka saya yakin Anda tidak harus mencoba untuk mendapatkan nama shell).Jadi saya kira Anda mengkodekan beberapa file sumber (mungkin menghasilkan satu) untuk mengkonfigurasi beberapa perangkat lunak. Jadi jelaskan saja apa yang Anda lakukan, dan kode untuk kasus umum
bash
(dan mungkinzsh
&tcsh
) ....sumber
gunakan di bawah ini dengan penafian risiko sendiri
sumber
-f
opsi dalamreadlink
, beberapa implementasi tidak memiliki saklar itu-f
sebagai opsi yang tersedia, menganggapnyaformat
sebagai argumen.readlink
tidak bekerja pada vm puredarwin saya jadi saya tidak tahu apa yang terjadi di sana.