Что не так с этим сценарием?

Таким образом, я получил этот сценарий от этого руководства: www.tldp.org/LDP/abs/abs-guide.pdf

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=86
E_NOTROOT=87

if [ "$UID" != "$ROOT_UID" ]
then
echo "Must be root to run this script."
exit $E_NOTROOT
fi

if [ -n "$1" ]
then
lines=$1
else
lines=$LINES
fi

cd $LOG_DIR

if [ 'pwd' != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi

Теперь я сделал sudo su на терминале и повторил $UID, который дает мне 0. Это означает мой, если условие оказывается ложью, но тем не менее я добираюсь, "Должен быть корень для запущения этого скрипта". при запущении этого скрипта.

Также в исходном сценарии это, если условие было дано как

if [ "$UID" -ne "$ROOT_UID" ]

но я получал Недопустимую ошибку числа, потому что, по-видимому-ne только используется для строки, таким образом, я изменил его на! =.

2
задан 22 August 2014 в 22:02

2 ответа

Вместо того, чтобы выполнить его с

sh script.sh

выполните его с

bash script.sh

(или добавить #!/bin/bash как первая строка, которая установит интерпретатор).

sh оболочка в Ubuntu не bash, но отдельная названная оболочка dash. dash не имеет стольких же функций сколько bash, который делает это более эффективным, но эти недостающие возможности иногда повреждают сценарии, предназначенные для bash. Одна такая функция $UID переменная, которая не определяется в dash.

Это означает это, когда сценарий выполняется в dash, сравнение станет ["" != "0"], который оценивает к истинному, какой пользователь выполняет его. Однако, если это выполняется в bash с корневыми полномочиями строки будут равны, и сценарий будет работать.

3
ответ дан 7 October 2019 в 05:21

Поскольку McLovin говорит, автоматически набор, только для чтения UIDEUID) переменная является специальной функцией bash (и некоторые другие оболочки). Это не стандартно для оболочек стиля Границы и sh как может предполагаться, не устанавливает эти переменные. В частности, sh в Ubuntu (в настоящее время, по умолчанию) dash, который не устанавливает их.

У Вас есть две опции:

  1. Заставьте свой сценарий быть выполненным bash вместо sh.
  2. Измените свой сценарий, таким образом, это более портативно и не требует bash.

Запущение Вашего скрипта с bash

Вы не сказали нам название своего сценария (который является хорошо). Я собираюсь назвать его cleanup, поскольку это - название подобного сценария в руководстве, Вы работаете от.

Обратите внимание в особенности, что я не называю его чем-то как cleanup.sh. Это вызвано тем, что я не рекомендую назвать его с a .sh суффикс:

  • A .sh суффикс предполагает, что это совместимо с sh!
  • Большинству сценариев не дают суффикс вообще, и имеющий a .sh или .bash суффикс может даже быть интерпретирован, поскольку предложение Вашего файла является "библиотекой", а не "высокоуровневым" сценарием. Таким образом, то, что это предоставляет код, который будет получен другими сценариями (например, с . встроенный), а не на самом деле выполненный непосредственно.

Однако включая a .sh суффикс не будет влиять на техническое поведение Вашего сценария всегда. Нет никакого технического преимущества или недостатка, связанного с выполнением так.

Добавьте hashbang строку как самую первую строку Вашего сценария: #!/bin/bash

Сделайте свой исполняемый файл сценария с chmod +x cleanup.

Теперь можно запустить скрипт путем выполнения команды:

  • ./cleanup, когда это находится в текущем каталоге. (Особенно при сценариях для образования, исследования, тестирования, забавы или другого ограниченного или одноразового использования, это - возможно, наиболее распространенный способ.)

  • /path/to/cleanup, в целом. Если первая команда содержит a / это интерпретируется как путь к исполняемому файлу. (Это - причина вышеупомянутого ./ синтаксис, как . означает текущий каталог.)

    Первым словом я имею в виду команду до, но не включая ее первое незавершенное пространство или вкладку:
    foo-bar/baz первое слово foo-bar/baz qux, в то время как spam\ ham первое слово spam\ ham eggs потому что пространство прежде ham оставлен с обратной косой чертой.

  • cleanup, если это находится в каталоге в Вашем PATH (и никакой каталог не перечислил, сначала имеет исполняемый файл того же имени, и оно не заменяется встроенной оболочкой, функция или псевдоним).

Независимо от действительно ли сценарий cleanup имеет a #!... строка hashbang или что говорит та строка:

  • sh cleanup будет все еще (попытаться к), выполняет его с sh как интерпретатор.
  • bash cleanup будет все еще (попытаться к), выполняет его с bash как интерпретатор.

Это вызвано тем, что в тех случаях Вы на самом деле выполняете интерпретатор (sh или bash) и передача названия сценария к интерпретатору, чтобы быть выполненным. Много программ принимают, что названия файлов открываются на командной строке и оболочках как sh и bash следуйте этой конвенции.

Создание Вашего портативного сценария

Если Вы хотите сделать свой сценарий портативным, самый простой путь не состоит в том, чтобы использовать $UID вообще, и вместо этого используйте некоторое средство, доступное всем оболочкам стиля Границы.

В целом нет никакого встроенного средства оболочки для определения идентификатора пользователя. Но можно использовать id. Это - внешняя программа, а не встроенная оболочка, но как cat и ls, разумно ожидать, что это будет присутствовать.

id отдельно производит набор информации, но id -u дает просто эффективный идентификатор пользователя.

Таким образом вместо if [ "$UID" != "$ROOT_UID" ], можно использовать:

if [ "$(id -u)" != "$ROOT_UID" ]

Технически, это не эквивалентно. $UID в bash дает идентификатор реального пользователя, и id -u действительно соответствует bash $EUID. Если Вы действительно хотите UID а не EUID, использовать id -ru.

1
ответ дан 7 October 2019 в 05:21

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

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