Яка різниця між "джерелом х", ". x "та" ./x "в Bash?


11

У мене є одне джерело баш, run.shяк описано нижче,

#!/bin/bash
if [ $# -ne 1 ]; then
    exit
fi
...

коли я виконую це двома способами, виникають різні поведінки. Перший спосіб -

source run.sh

Після закриття терміналу він закриється. Другий спосіб -

./run.sh

це просто закінчить виконання сценарію та залишиться на терміналі. Я запитую, чи є команда для виходу bash-скриптів і для виконання, source run.shі для ./run.shвиконання. Я returnтеж спробував , що не працює добре під час ./run.shвиконання.

Загалом, мене цікавить, чому це відбувається, і яка різниця між використанням "джерела" та "." для виконання сценарію?

Відповіді:


16

Перш ніж відповісти, я думаю, що потрібні деякі уточнення. Проаналізуємо наступні три рядки:

source run.sh
. run.sh
./run.sh

Перші два рядки абсолютно однакові: .насправді псевдонім для source. Що sourceтаке виконання скрипта оболонки в поточному контексті, отже, заклик до exitвиходу з оболонки.

Третій рядок (той, що вас бентежить), однак, не має нічого спільного з іншими рядками. ./run.shце лише шлях, і це те саме, що (наприклад) /home/user/run.shабо /usr/bin/something. Завжди пам’ятайте, що команди в оболонці розділені пробілом. Отже, у цьому випадку команда не є ., а є ./run.sh: це означає, що підколота буде виконана і що exitдія матиме ефект саме для підкошти.


5

Три способи:

Ви можете долучити скрипт до функції і використовувати лише return.

#!/usr/bin/env bash
main() {
    ...
    return 1
    ...
}
main "$@"

Ви можете перевірити, чи використовується сценарій інтерактивною оболонкою.

if [[ $- = *i* ]]; then
    return 1
else
    exit 1
fi

Ви можете спробувати повернутися, і якщо це не вдасться, вийдіть.

return 1 2>/dev/null || exit 1

Будь-які натяки на те, як працює магічний заповіт $- = *i* ?
deadbeef404

@ deadbeef404 Спеціальний параметр -містить поточно активні прапори опцій. Тест перевіряє, чи відповідає-i прапор активний. Дивіться gnu.org/software/bash/manual/html_node/Special-Parameters.html
geirha

1

Подумайте про команду 'source', як у операції 'include'. Він бере зміст аргументу і запускає його так, як ніби він був запущений безпосередньо. У цьому випадку ваша команда - "джерело" з аргументом "run.sh", а run.sh виконується точно так, як би ви ввели вміст run.sh у свій командний рядок.

Коли ви запускаєте './run.sh', './run.sh' - це ваша команда, і вона не має аргументів. Оскільки цей файл є текстовим та не двійковим, ваша оболонка шукає інтерпретатора в shebang ('#!' В першому рядку) і знаходить '/ bin / bash'. Тоді ваша оболонка запускає новий екземпляр bash, а вміст run.sh запускається всередині цього нового екземпляра.

У першому випадку, коли bash досягає команди 'exit', він виконується точно так, як би ви ввели його в командний рядок. У другому випадку він виконується в баш-процесі, і ваша оболонка запускається, таким чином, лише цей екземпляр bash отримує команду 'exit'.

Коли ви вводите рядок у bash, все, що перед першим пробілом, трактується як команда, а все, що випливає, трактується як аргументи. Команда '.' є псевдонімом "джерела". Коли ти біжиш '. run.sh 'the'. " це власна команда, оскільки вона відокремлена від аргументів пробілом. Коли ви запускаєте './run.sh', ваша команда - './run.sh' і '.' є частиною відносного шляху до run.sh з '.' що представляє вашу поточну папку.


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