Pertanyaan Bagaimana skrip saya menentukan apakah itu dijalankan oleh bash atau dash?


Saya sedang menjalankan instalasi Oneiric baru (yaitu bukan peningkatan versi) pada dua sistem yang berbeda dan mengalami masalah yang tampaknya terkait.

Yang paling membuat frustrasi adalah, ketika saya menggunakan .profile dan .bashrc yang saya bawa dari Mac OS X, masuk ke X via LightDM segera log saya. Saya yakin ini disebabkan oleh fakta bahwa ketika menjalankan "/ bin / sh", ia berperilaku sebagai / bin / dash, tetapi masih memiliki variabel $ SHELL yang disetel ke / bin / bash.

Ekstrapolasi

Saya memiliki besar .bashrc. Kamu bisa melihatnya sini jika Anda ingin, tetapi isinya mungkin tidak relevan, selain dari fakta bahwa itu penuh bashisms, dan fakta bahwa ia bekerja tanpa kesalahan di dalam xterm atau pada konsol virtual.

Saya .profile terlihat seperti ini (disingkat):

case $SHELL in 
*bash*)
    if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
        . $HOME/.bashrc
    fi
    ;;
esac

Jika saya mencoba masuk ke X melalui LightDM, itu akan segera membuat saya keluar. Saya mendapat kesalahan .xsession-errors berkaitan dengan .bashrc saya yang terlihat seperti ini (disingkat):

/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found

Seperti yang saya katakan, ketika saya menjalankan bash dari konsol virtual, saya tidak mendapatkan kesalahan ini. Selanjutnya, jika saya menghapus profil saya. Saya dapat masuk ke X dengan baik. (Saya juga bisa masuk ke konsol virtual dan menggunakannya startx untuk memulai sesi X yang berfungsi, tetapi ini tentu saja bukan solusi jangka panjang.)

Namun, saya menemukan bahwa jika saya lari /bin/sh -lAku melakukan dapatkan kesalahannya. Berikut ini contoh sesi (catatan: prompt bash yang saya sederhanakan bash>, dan sh tepat $):

bash> echo $SHELL
/bin/bash
bash> echo $BASH_VERSION
4.2.10(1)-release
bash> /bin/sh -l
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION

$

Q1: Mengapa ini terjadi?

aku mengerti itu / bin / sh sekarang mengarah ke dash daripada bash, tetapi jika itu benar, lalu mengapa $SHELL masih kembali /bin/bash?

Q2: Apa yang bisa saya lakukan untuk mengatasinya?

Apakah ada cara untuk mengatasi hal ini? Saya ingin menjaga profil saya memuat .bashrc sehingga saya mendapatkan lingkungan yang sama di kedua cangkang login dan non-login, tetapi jelas saya hanya ingin memuat untuk bash itu sendiri, tidak / bin / sh menyamar sebagai bash.

Anda mungkin telah memperhatikan perbedaan dalam isi variabel $ BASH_VERSION di atas. Saya telah mencoba membungkus profil saya. Dalam sesuatu seperti ini:

if [ -n $BASH_VERSION ]; then
    # the rest of my .profile as above
fi

Itu -n uji harus mengembalikan true hanya jika panjang string tidak nol, namun, meskipun pada sesi di atas, ketika saya berjalan di bawah /bin/sh -l ia mengembalikan string kosong untuk $ BASH_VERSION, ketika itu termasuk dalam .profile saya seperti ini, ia lulus ujian! Itu mereka hasil ke sumber saya. Bashrc dan memberi saya kesalahan yang sama seperti sebelumnya.

Sekarang saya sangat bingung.


12
2018-01-22 06:08


asal


Perhatikan itu dash -l juga menunjukkan $SHELL memiliki nilai /bin/bash. - Scott Severance
$SHELL adalah apa pun bidang terakhir di /etc/passwd (atau getent passwd) mengatakan. - Dennis Williamson
@DennisWilliamson Terima kasih, itulah yang perlu saya ketahui untuk menemukan jawaban yang benar. - Micah R Ledbetter
Kamu melakukannya dengan salah. Anda harus menempatkan lingkungan non-bash-spesifik di ~/.profile, hal-hal spesifik-bash dalam ~/.bashrc, dan miliki ~/.bash_profile sumber keduanya. - nyuszika7h


Jawaban:


Anda dapat membuat fakta itu $BASH_VERSION kosong dash bekerja untukmu:

if [ "$BASH_VERSION" = '' ]; then
    echo "This is dash."
else
    echo "This is bash."
fi

11
2018-01-22 09:47



Teknik "x" adalah kuno dan hanya dibutuhkan di kuno kerang. Menggunakan if [ "$BASH_VERSION" = '' ] - Dennis Williamson
@DennisWilliamson: Terima kasih. Saya pikir teknik Anda khusus untuk Bash, tapi saya hanya beristirahat di Dash dan itu berhasil. Saya telah mengedit jawaban saya. - Scott Severance
Atau hanya menggunakan -n, atau tidak ada. (+1, meskipun. = '' bekerja dengan sangat baik.) - Eliah Kagan


Anda hanya perlu menggunakan tanda kutip pada variabel BASH_VERSION menggunakan -n

if [ -n "$BASH_VERSION" ];then
 echo "this is bash"; 
else 
 echo "this is dash";
fi

5
2018-05-13 14:29



sejak [ "$EMPTY_STRING" ] mengevaluasi salah, Anda bahkan tidak membutuhkan -n. Anda hanya perlu mengutip variabel. - jeberle


Menggunakan /proc/[PID]/cmdline untuk melihat apa skrip yang dijalankan dan menguji apa yang dikandungnya. Itu $$ variabel akan memberi kita PID dari shell yang sedang berjalan. Jadi kita bisa membuat naskah seperti ini,

#!/bin/bash
if grep -q 'bash' /proc/$$/cmdline ;
then
    echo "This is bash"
else
    echo "This is some other shell"
fi

Berikut tes skrip yang sama:

$> bash test_script.sh                                                                                                
This is bash
$> dash test_script.sh                                                                                                
This is some other shell

1
2018-04-06 14:45



Ini tidak akan berfungsi di Mac. Periksa $ BASH_VERSION. - Austin Burk
@AustinBurk tidak perlu bekerja pada Mac. Ini Tanya Ubuntu. - TheWanderer
@ Zacharee1 oh sialan, saya tidak memperhatikan:,) - Austin Burk
Saya tidak ingin mengedit ini dari apa yang Anda maksudkan, tetapi saya sarankan menyebutkan keterbatasan metode ini. Bash tidak perlu bash atas namanya; itu tidak biasa untuk bash dieksekusi untuk dijalankan melalui symlink dengan nama lain. Biasanya orang masih ingin mempertimbangkan Bash itu. Juga, polanya cocok di mana saja di /proc/$$/cmdline, yang harus mungkin untuk diperbaiki, tetapi perlu diingat bahwa argumen dalam cmdline adalah null-character delimited. grep -qE '(^|/)bash$' merasa seperti itu seharusnya bekerja tetapi memberikan false positive ketika ada argumen bash. - Eliah Kagan
@EliahKagan Jangan sungkan untuk mengedit jawaban saya kapan saja - Anda memiliki keahlian yang cukup sehingga saya tahu hasil edit Anda hanya dapat menawarkan peningkatan. Jawabannya ditulis ketika saya jauh lebih hijau dengan cangkang daripada saya sekarang. - Sergiy Kolodyazhnyy