Как мой сценарий может определить, выполняется ли он с помощью bash или dash?


13

Я запускаю новую установку Oneiric (то есть не обновление) на двух разных системах и сталкиваюсь с одним и тем же набором, казалось бы, связанных проблем.

Самое расстраивающее из этого - то, что, когда я использую .profile и .bashrc, которые я взял с собой из Mac OS X, вход в X через LightDM выводит меня из системы немедленно. Я полагаю, что это связано с тем, что при запуске «/ bin / sh» он ведет себя как / bin / dash, но все еще имеет переменную $ SHELL, установленную в / bin / bash.

экстраполяция

У меня огромный .bashrc. Вы можете увидеть его здесь, если хотите, но его содержимое, вероятно, не имеет значения, за исключением того факта, что он полон ошибок, и того факта, что он работает без ошибок внутри xterm или на виртуальной консоли.

Моя .profileвыглядит так (сокращенно):

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

Если я попытаюсь войти в X через LightDM, он сразу же выйдет из системы. Я получаю ошибки в .xsession-errorsотношении моего .bashrc, которые выглядят так (сокращенно):

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

Как я уже сказал, когда я запускаю bash с виртуальной консоли, я не получаю этих ошибок. Кроме того, если я удаляю свой .profile, я могу войти в X очень хорошо. (Я также могу войти в виртуальную консоль и использовать ее startxдля запуска сеанса X, который работает, но это, конечно, не долгосрочное решение.)

Тем не менее, я обнаружил , что если я бегу /bin/sh -l, я бы получить ошибки. Вот пример сеанса (примечание: приглашение bash, которое я упростил bash>, и приглашение sh просто $):

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: почему это происходит?

Я понимаю, что / bin / sh теперь указывает на тире, а не на bash , но если это правда, то почему $SHELLвсе еще возвращается /bin/bash?

Q2: Что я могу сделать, чтобы обойти это?

Есть ли способ обойти это? Я хочу, чтобы мой профиль загружался в .bashrc, чтобы получить одинаковую среду как для входа в систему, так и для входа в систему, но не для входа в систему, но, очевидно, я хочу, чтобы он загружался только для самого bash, а не / bin / sh, маскируясь под bash.

Возможно, вы заметили разницу в содержании переменных $ BASH_VERSION выше. Я попытался обернуть мой .profile примерно так:

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

-nТест должен возвращать верно , только если длина строки не равна нулю, однако, несмотря на то, на сессии выше, когда я под управлением операционной системы/bin/sh -l это возвращает пустую строку $ BASH_VERSION, когда он включен в моем .profile , как это Пройди тест! Он продолжает исходить из моего .bashrc и выдает мне те же ошибки, что и раньше.

Теперь я действительно запутался.


Обратите внимание, что dash -lтакже показывает $SHELLналичие значения /bin/bash.
Скотт Северанс

3
$SHELLэто то, что говорит последнее поле в /etc/passwd(или getent passwd).
Приостановлено до дальнейшего уведомления.

@DennisWilliamson Спасибо , это то, что мне нужно было знать, чтобы найти правильный ответ.
Мика Р Ледбеттер

Ты делаешь это неправильно. Вы должны поместить среду ~/.profile, не относящуюся к bash, в вещи, относящиеся к bash ~/.bashrc, и иметь ~/.bash_profileисточник обоих.
nyuszika7h

Ответы:


12

Вы можете сделать тот факт, что $BASH_VERSIONпуст в dashработе для вас:

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

2
Техника «х» архаична и нужна только в древних ракушках. Использованиеif [ "$BASH_VERSION" = '' ]
приостановлено до дальнейшего уведомления.

@DennisWilliamson: Спасибо. Я думал, что ваша техника специфична для Bash, но я просто остановил ее в Dash, и она сработала. Я отредактировал свой ответ.
Скотт Северанс

Или просто использовать-n , или ничего . (+1, хотя. = ''Отлично работает.)
Элия ​​Каган

5

Вы просто должны использовать кавычки для переменной, BASH_VERSIONчтобы использовать-n

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

1
так как [ "$EMPTY_STRING" ]оценивает false, вам даже не нужно -n. Вам просто нужно процитировать переменную.
Джеберль

2

Используйте, /proc/[PID]/cmdlineчтобы увидеть, с чем запускается скрипт, и проверить, что он содержит. $$Переменный даст нам PID запущенной оболочки. Таким образом, мы можем сделать такой скрипт,

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

Вот тест того же скрипта:

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

Это не будет работать на Mac. Проверьте $ BASH_VERSION.
Остин Берк,

2
@ AustinBurk это не должно работать на Mac. Это Ask Ubuntu.
Странник

@ Zacharee1 о штопка это, я не обращала внимания:,)
Остин Берк

Я не хочу редактировать это вне того, что вы намереваетесь, но я предлагаю упомянуть ограничения этого метода. Bash не должен иметь bashв своем названии; нередко bashзапуск исполняемого файла осуществляется по символической ссылке с другим именем. Обычно все-таки хочется рассмотреть этот Баш. Кроме того , картина соответствует где - нибудь в/proc/$$/cmdline , что должно быть возможно исправить, но имейте в виду , что аргументы в cmdlineнуль-символ разграничены. grep -qE '(^|/)bash$'кажется, что это должно работать, но дает ложный положительный результат, когда любой аргумент bash.
Элия ​​Каган,

@EliahKagan Не стесняйтесь редактировать мои ответы в любое время - у вас достаточно опыта, поэтому я знаю, что ваши изменения могут предложить только улучшения. Ответ был написан, когда я был намного зеленее с раковинами, чем сейчас.
Сергей Колодяжный
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.