сценарий удара: различные результаты при вызове или без sudo

В Ubuntu 16.04.3 у меня есть очень простой сценарий удара:

test.sh

[[ 0 == 0 ]] && result="true" || result="false"
echo $result
echo $USER $SHELL $0

Когда я называю его как некорневой пользователь me или как root, это работает как ожидалось. Если я использую sudo ./test.sh, это жалуется на синтаксическую ошибку:

$ ./test.sh
true
me /bin/bash ./test.sh

$ sudo su
# ./test.sh 
true
root /bin/bash ./test.sh

# exit
$ sudo ./test.sh
./test.sh: 1: ./test.sh: [[: not found
false
root /bin/bash ./test.sh

Что могло вызывать это? Как я могу зафиксировать его так, чтобы me может использовать этот сценарий и обычно и с sudo?

10
задан 25 November 2017 в 17:24

2 ответа

Каждый сценарий начинается с Хижины без него, оболочка, начинающая Ваш сценарий, не знает, какой интерпретатор должен выполнить Ваш script1, и мог бы – как в случае sudo ./script.sh здесь – выполняет его с sh, который в Ubuntu 16.04 связан с dash. Условное выражение [[ a bash соедините команду, таким образом, dash не знает, как обработать его и бросает ошибку, с которой Вы встретились.

Решение здесь состоит в том, чтобы добавить

#!/bin/bash

как первая строка Вашего сценария. Можно получить тот же результат при вызове его явно с sudo bash ./script.sh, но хижина является способом пойти.
Для проверки, какая оболочка запускает скрипт добавить echo $0 к нему. Это не то же как echo $SHELL, цитирование wiki.archlinux.org:

SHELL содержит путь к предпочтительной оболочке пользователя. Обратите внимание, что это - не обязательно оболочка, которая в настоящее время работает, хотя Bash устанавливает эту переменную на запуске.

1: Поскольку Вы запустили ./test.sh с bash это просто приняло bash, то же идет для sudo su подоболочка.

20
ответ дан 25 November 2017 в 17:24

Как @dessert объясненный, проблема здесь состоит в том, что Ваш сценарий не имеет строки хижины. Без хижины, sudo примет значение по умолчанию к попытке выполнить использование файла /bin/sh. Я не мог найти, что это зарегистрировало где угодно, но я подтвердил путем проверки sudo исходный код, где я нашел следующее в файле pathnames.h:

#ifndef _PATH_BSHELL
#define _PATH_BSHELL "/bin/sh"
#endif /* _PATH_BSHELL */

Это означает "набор если переменная _PATH_BSHELL не определяется, установите его на /bin/sh". Затем в configure сценарий включал в источник tarball, мы имеем:

for p in "/bin/bash" "/usr/bin/sh" "/sbin/sh" "/usr/sbin/sh" "/bin/ksh" "/usr/bin/ksh" "/bin/bash" "/usr/bin/bash"; do
    if test -f "$p"; then
    found=yes
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $p" >&5
$as_echo "$p" >&6; }
    cat >>confdefs.h <<EOF
#define _PATH_BSHELL "$p"
EOF

    break
    fi
done

Этот цикл будет искать /bin/bash, /usr/bin/sh, /sbin/sh, /usr/sbin/sh или /bin/ksh и затем наборы _PATH_BSHELL к тому, какой бы ни был найден первым. С тех пор /bin/sh было первым в списке, и он существует, _PATH_BSHELL установлен на /bin/sh. Результат всего этого состоит в том что оболочка по умолчанию sudo если иначе не определено /bin/sh.

Так, sudo примет значение по умолчанию к рабочим вещам, использующим /bin/sh и, на Ubuntu, которая является символьной ссылкой на dash, минимальный POSIX совместимая оболочка:

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 27  2015 /bin/sh -> dash

[[ конструкция является функцией удара, она не определяется стандартом POSIX и не понята под dash:

$ bash -c '[[ true ]] && echo yes'
yes
$ dash -c '[[ true ]] && echo yes'
dash: 1: [[: not found

Подробно, в этих трех вызовах Вы попробовали:

  1. ./test.sh

    Нет sudo; в отсутствие строки хижины Ваша оболочка попытается выполнить сам файл. Так как Вы работаете bash, это будет эффективно работать bash ./test.sh и работа.

  2. sudo su сопровождаемый ./test.sh.

    Здесь, Вы запускаете новую оболочку для пользователя root. Это будет любой оболочкой, определяется в $SHELL переменная среды для того пользователя и, на Ubuntu, оболочка корня по умолчанию bash:

    $ grep root /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    
  3. sudo ./test.sh

    Здесь, Вы позволяете sudo выполните команду непосредственно. Так как его оболочка по умолчанию /bin/sh как объяснено выше, это заставляет это запускать скрипт с /bin/sh, который является dash и это перестало работать с тех пор dash не понимает [[.


Примечание: детали как sudo наборы оболочка по умолчанию, кажется, немного более сложны. Я пытался изменить файлы, упомянутые в моем ответе для указания на /bin/bash но sudo все еще принимал значение по умолчанию к /bin/sh. Таким образом, должны быть некоторые другие места в исходном коде, где оболочка по умолчанию определяется. Тем не менее, основной момент (это sudo значения по умолчанию к sh) все еще стоит.

5
ответ дан 25 November 2017 в 17:24

Другие вопросы по тегам:

Похожие вопросы: