9

Есть ли способ запустить сценарий оболочки с выводом команд, но без их выполнения?

Допустим, у меня есть скрипт, удаляющий файл, имя которого хранится в переменной:

#!/bin/bash
set -v
FN="filename"
rm -f ${FN}

Добавление set -v выдает следующие команды перед выполнением:

$ ./scr.sh
FN="filename"
rm -f ${FN}

Теперь я хочу увидеть поток этого сценария без фактического удаления файла. Я хочу предотвратить любое воздействие на внешнюю среду и файловую систему. Это возможно?

Я мог бы обернуть все команды командой echo , но это утомительно для длинного сценария.

7 ответов7

7

Нет способа пройтись по сценарию, чтобы увидеть, как он будет выполняться без этого. В вашем примере нет операторов if или циклов. Но в реальных сценариях часто встречается много условных выражений. Какая ветвь будет получена, часто зависит от того, что произошло, когда оболочка выполнила предыдущую команду. Если она не запускает команду, оболочка не может узнать, какой вывод она сгенерировала или какой код возврата был бы, от чего могла бы зависеть следующая условная ветвь или оператор присваивания.

Если дело в том, что вы хотите тщательно изучить скрипт и знать, что он делает, прежде чем запускать его, это неплохая идея. Но на самом деле, лучший способ сделать это - просто просмотреть файл с помощью less или vi или чего-то подобного.

добавленной

Если вы разрабатываете сценарий и хотите в первый раз пройтись по нему, тестируя логику, но на самом деле не причиняя вреда, если у вас есть ошибка, решение, которое я часто могу использовать, заключается в изменении только заявления, которые могут нанести какой-либо ущерб, вставив echo на фронт.

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

6

Я думаю, что вам придется повторить - однако, если вы поместите команду в переменную, вы можете включить и выключить ее. Кроме того, команда может быть функцией и настолько сложной, насколько вы хотите.

#!/bin/bash
echo 'Debug'
  D=echo
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy
echo $'\n\nLive'
  D=
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy

!$ > ./conditional.sh
Debug
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
rm -f testy
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy

Live -rw-rw-r-- 1 никто никто 0 2013-01-18 15:28 testy ls: не может получить доступ к testy: нет такого файла или каталога

4

Вы отслеживаете поток, используя опцию -x для bash, но это все равно будет выполнять команды.

Лучшее, что вы можете сделать, это просто вставить echo или закомментировать команды, которые имеют внешние эффекты, такие как rm. По крайней мере, вам не нужно менять каждую строку.

2

set –n или добавьте n к существующей команде set –v .  Но так как это заставляет оболочку не оценивать какие-либо команды, даже if или while , вы можете не получить слишком хорошее представление о рабочем процессе.

2

Я не знаю какого-либо конкретного метода для пробного запуска, но мы можем использовать некоторые меры предосторожности для понимания неизвестного сценария.

  1. Используйте среду chroot для запуска вашего сценария отладки. Он будет действовать как песочница и обеспечит защиту от удаления / изменения основных системных файлов.
  2. Используйте bash -n <script> для проверки синтаксиса. Из руководства gnu bash https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

-n Read commands but do not execute them; this may be used to check a script for syntax errors. This option is ignored by interactive shells.

  1. Прочитайте сценарий хотя бы один раз. Вы можете использовать оператор echo для отладки, как указано в ответе пользователя191016 .
    • Обращайте внимание на подозрительный или опасный код.
    • например, связанные с rm, команды, влияющие на /dev /sda и т. д.
  2. Всегда старайтесь запускать сценарии от имени обычного пользователя, избегайте запуска неизвестных сценариев от имени пользователя root.
  3. Вы можете определить псевдоним для создания команды, которая может изменять файлы как интерактивные при запуске вашего скрипта. Пример alias rm="rm -i" alias cp="cp -i" alias mv="mv -i" Для потоковых редакторов, таких как sed sed -i (-i изменяет файл на месте без -i, он выполняет пробный запуск для sed, проверьте страницу руководства для получения подробной информации). Вы можете скопировать всю команду и запустить. Непосредственно перед самой командой будет отображаться вывод на экране, а затем используется команда для ожидания продолжения ввода пользователя. Пример sed -i <pattern> Замените его на sed <pattern> read -p "Press any key..." sed -i <pattern>

Также всегда рекомендуется сохранить резервные точки в вашей системе, чтобы в случае чрезвычайной ситуации данные можно было восстановить.

2

Вот небольшая конструкция, которую я люблю использовать:

#!/bin/sh

verbose=false
really=true

# parse arguments
while [ $# -ge 1 ]
do
  case "$1" in
    -v) verbose=true ;;
    -n) really=false; verbose=true ;;
  esac
  shift
done

doCmd() {
  if $verbose; then echo "$@"; fi
  if $really; then "$@"; fi
}

doCmd make foo
doCmd rm -rf /tmp/installdir
doCmd mkdir /tmp/installdir
doCmd whatever
doCmd blah blah
1

Если вы хотите предотвратить изменения, вы можете запустить скрипт как пользователь без привилегий:

sudo -u nobody ./scr.sh

В вашем примере это будет выполнять FN="filename" как обычно. Хотя технически он также выполняет команду rm -f ${FN} , ничего не произойдет, если никто не имеет необходимых разрешений для удаления файла.

Конечно, это вызовет проблемы с условным рабочим процессом. Тот факт, что команда rm не удалась, может повлиять на дальнейшие части скрипта.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .