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

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

Итак, я взял этот скрипт из этого руководства: 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 оказалось ложным, но я все равно получаю сообщение «Для запуска этого скрипта требуется root» при запуске этого скрипта.

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

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

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

решение1

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

sh script.sh

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

bash script.sh

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

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

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

решение2

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

У вас есть два варианта:

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

Запуск вашего скрипта с помощьюbash

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

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

  • Суффикс .shпредполагает совместимость с sh!
  • Большинству скриптов вообще не дается суффикс, а наличие суффикса .shили .bashможет даже быть интерпретировано как предположение, что ваш файл является «библиотекой», а не скриптом «верхнего уровня». То есть, он предоставляет код, который будет использоваться другими скриптами (например, встроенным .), а не будет запущен напрямую.

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

Добавитьлиния хэшбэнгакак в самой первой строке вашего скрипта:#!/bin/bash

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

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

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

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

    Кпервое словоЯ имею в виду команду до, но не включая ее первуюнеэкранированныйпробел или табуляция:
    foo-bar/bazявляется первым словом foo-bar/baz qux, в то время как spam\ hamявляется первым словом , spam\ ham eggsпоскольку пробел перед ним hamэкранируется обратной косой чертой.

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

Независимо от того, есть ли сценарий или нетcleanupимеет #!...строку с хэшбэнгом или что-то в этом роде:

  • sh cleanupвсе равно (попытаюсь) запустить его shв качестве интерпретатора.
  • bash cleanupвсе равно (попытаюсь) запустить его bashв качестве интерпретатора.

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

Сделайте свой скрипт портативным

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

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

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

Поэтому вместо if [ "$UID" != "$ROOT_UID" ], вы можете использовать:

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

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

Связанный контент