Як перегукувати команди в скрипті bash shell, але не виконувати їх?


9

Чи існує спосіб запуску скрипта оболонки з повторюваними командами, але без їх виконання?

Скажімо, у мене є скрипт для видалення файлу, ім'я якого зберігається у змінній:

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

Додавання set -vповторює наступні команди перед виконанням:

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

Тепер я хочу побачити потік цього сценарію без фактичного видалення файлу. IOW, я хочу запобігти будь-якому впливу на зовнішнє середовище та файлову систему. Чи можливо це?

Я міг обернути всі команди echoкомандою, але це втомлює довгий сценарій.


Я не фахівець з скриптових сценаріїв, але якби писав це іншою мовою програмування, я б зберігав усі команди в масиві. таким чином слід легко пропустити цикл і виконати команди або роздрукувати їх.
hugo der hungrige

Відповіді:


8

Немає способу переступити через скрипт, щоб побачити, як він би виконувався, а не робити цього. У вашому прикладі немає ifзаяв чи циклів. Але в реальних сценаріях часто існує багато умовних тверджень. Яка гілка буде взята, часто залежить від того, що сталося, коли оболонка виконувала попередню команду. Якщо вона не запускає команду, оболонка не може знати, який вихід буде створений або яким би був код повернення, від якого може залежати наступна умовна гілка або оператор призначення.

Якщо справа в тому, що ви хочете перевірити сценарій і знати, що він робить, перш ніж запустити його, це не погана ідея. Але реально, про кращий спосіб зробити це, просто переглядає файл з lessабо viабо що - щось подібне.

Додано

Якщо ви розробляєте скрипт, і хочете вперше пройти його, перевіряючи логіку, але насправді не завдаючи шкоди, якщо у вас є помилка, рішення, яке я часто можу використовувати, - це лише змінити заяви, які можуть завдати будь-якої шкоди, вставивши echoна передню частину.

Це часто працює в типових сценаріях реального життя, оскільки (a) генерування списків елементів, які ви повторите, або значення, до якого ви встановите змінну, часто можна генерувати без зміни файлової системи, і (b) зазвичай достатньо припустимо, що якби ви запустили команду, це вдасться.


Дякую. Мене здивувало б, якщо є спосіб саме через причину, яку ви згадали, але я все-таки вирішив спробувати. Причиною цього є те, що я розробляю сценарій, який переміщує файли на багатьох машинах у мережі та виконує деякі дії на віддалених хостах. Я хотів би побачити потік сценарію, перш ніж здійснити зміни у файловій системі. Було б так само нудно перебирати всі віддалені машини, щоб виправити помилки файлів ...
ysap

1
Додаток: Щоб перейти через сценарій, ви можете запустити скрипт, за допомогою trap read debugякого буде читатись після кожного виконаного рядка, а потім ви можете повільно переходити через нього з введенням (це корисно, якщо у вас дійсно довгий сценарій і хочете перевірити це вперше).
нетиггер

7

Я думаю, що вам доведеться лунати, але якщо ви введете команду в змінну, ви можете її включати та вимикати. Також команда може бути функцією і настільки складною, як вам хочеться.

#!/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 nobody nobody 0 2013-01-18 15:28 testy ls: cannot access testy: No such file or directory


Мені потрібні лапки в командах ехо / не-ехо, а потім довелося використовувати D=evalв реальній частині. Але приємна відповідь!
Джаспер

5

Ви простежуєте потік, використовуючи опцію -x для bash, але це все одно виконує команди.

Найкраще, що ви могли зробити, це просто поставити ехо або прокоментувати команди, які мають зовнішні ефекти, такі як rm. Принаймні, вам не доведеться змінювати кожен рядок.


Дякую. Я згадував цей варіант у своєму питанні, але він насправді не вирішує мою проблему.
ysap

Вибачте, я думав, що ви маєте на увазі повторення кожного рядка, -x зменшить це до кількох команд і покаже вам оцінки.
parkydr

3

Виконайте set –nабо додайте nдо існуючої set –vкоманди. Але оскільки це призводить до того, що оболонка не оцінює жодних команд, навіть, ifабо while, можливо, ви не отримаєте надто хорошого огляду операційного потоку.


Дякую. Це вдалий початок, але, як ви вже згадували, це не дає мені бачити фактичний потік - де в моєму реальному сценарії я маю петлю над списком віддалених хостів.
ysap

3

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

  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 змінює файл на місці без -я він робить сухий запуск для sed, перевіряйте man сторінку для деталей). може скопіювати повну команду та запустити. Незадовго до фактичної команди він покаже вихід на екрані, а потім скористайтеся командою, щоб зачекати, коли введення користувача продовжиться. Приклад sed -i <pattern> Замініть його на sed <pattern> read -p "Press any key..." sed -i <pattern>

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


3

Ось невеликий конструкт, який я хотів би використовувати:

#!/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

2

Якщо ви хочете не допустити змін, ви можете запустити сценарій як користувач без привілеїв:

sudo -u nobody ./scr.sh

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

Звичайно, це спричинить проблеми з умовним робочим процесом. Те, що rmкоманда не вдалася, може вплинути на подальші частини сценарію.


Речі, які ми ніколи не зрозуміємо: Чому root потрібно виконувати як ніхто ...
mjohnsonengr

Користувач "ніхто" не характерний для ОС, але ви можете додати запис у файл sudoers, що дозволяє без паролів sudo для "нікого".
Денніс

Я не знаю. Здається, що сценарій припиниться через певну або іншу помилку до його закінчення.
Едвард Фолк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.