Як викликати один скрипт оболонки з іншого сценарію оболонки?


737

У мене є два сценарії оболонки, a.shі b.sh.

Як мені зателефонувати b.shз скрипту оболонки a.sh?


8
Чи можете ви надати якусь специфіку: яка ОС та котрий оболонки (огляди) або ви в принципі просто говорите про цю проблему ?? Корисний також приклад коду.
jsalonen

14
Це насправді не конкретне питання, а також не демонструє попередніх зусиль для вирішення цього питання.
Кріс

1
Одне питання, яке у мене виникло, було те, що b.shне було дозволів на виконання файлів. Це може бути непогано перевірити.
seth10

Додайте ./перед назвою сценарію, наприклад b.sh, використовуйте:./b.sh
Benny

1
Якщо хто -то продовжує отримувати No such file or directoryпомилки stackoverflow.com/a/2920431/1356559
Амр Лотфі

Відповіді:


957

Є кілька різних способів зробити це:

  1. Зробіть інший виконуваний сценарій, додайте #!/bin/bashрядок у верхній частині та шлях, де знаходиться файл, до змінної середовища $ PATH. Тоді ви можете називати це звичайною командою;

  2. Або називайте його sourceкомандою (псевдонім є .) так source /path/to/script:;

  3. Або використовувати bashкоманду для його виконання: /bin/bash /path/to/script;

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

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


30
пам'ятайте, chmod a+x /path/to/fileінакше це не буде виконаним. Застосовується лише до ./script методу.
Натан Ліліенталь

3
Не забудьте змінити формат / кодування виконуваних файлів в unix, якщо вони створені в DOS і потім завантажені в середовище unix -> dos2unix <ім'я сценарію>
Abhishek Chatterjee

3
@cecemel Перший і третій спосіб можна "асинхронізувати", використовуючи звичайний синтаксис запущеного фону.
Якийсь програміст чувак

16
Проблема sourceполягає в тому, що exitвислів у закликаному сценарії вийде і з вашого ...
Охад Шнайдер

18
@ user528025 .- це не псевдонім source, а навпаки. sourceє розширенням bash, але .працює в будь-якій сумісній з POSIX оболонці.
Score_Under

207

Заціни.

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."

4
Це передбачає, що script.sh знаходиться в тому ж каталозі, що і будь-який сценарій, який виконується. Якби ви хотіли зателефонувати за сценарієм десь в іншому місці, ви б сказалиsh <path to script>/script.sh
Morgan Kenyon

32
Для цього також використовуються дві оболонки bashта sh. Навіть коли shнасправді bashвін поводиться не так. Якщо ви використовуєте, #!/bin/bashто, ймовірно, ви хочете використовувати bash script.sh(або просто ./script.shвикористовувати хешбанг сценаріїв).
Мартін Турноїй

1
Отримано дозвіл відхилено помилку, навіть коли я встановив chmod +xфайл .sh. Будь-які пропозиції?
isaac погода

@isaacweathers спробуйте chmod 777
Джанак Мена

114

Є кілька способів зробити це. Термінал для виконання сценарію:

#!/bin/bash
SCRIPT_PATH="/path/to/script.sh"

# Here you execute your script
"$SCRIPT_PATH"

# or
. "$SCRIPT_PATH"

# or
source "$SCRIPT_PATH"

# or
bash "$SCRIPT_PATH"

# or
eval '"$SCRIPT_PATH"'

# or
OUTPUT=$("$SCRIPT_PATH")
echo $OUTPUT

# or
OUTPUT=`"$SCRIPT_PATH"`
echo $OUTPUT

# or
("$SCRIPT_PATH")

# or
(exec "$SCRIPT_PATH")

Все це правильно для шляху з пробілами !!!


41
У чому їх відмінності? Чому одне, чому інше?
rocketspacer

. Краще "$ SCRIPT_PATH"
Гаррі Мамфорд-Тернер

1
Я можу лише додати, що це не всі еквіваленти, наприклад, sh "$ SCRIPT_PATH" і bash "$ SCRIPT_PATH" не запускається сценарій #! / Usr / bin / очікувати, тоді як просто "$ SCRIPT_PATH" буде.
Тахлор

58

Відповідь, яку я шукав:

( exec "path/to/script" )

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

EDIT: Насправді ( "path/to/script" )достатньо.


11
Це здається досить заплутаним. Чому б просто не назвати це /path/to/script? Я взагалі не бачу потреби execв цьому?
Мартін Турнойж

Абонентська оболонка також не потрібна, оскільки ви не працюєте exec.
Karel Vlk

6
як би ти виконав цей сценарій з аргументами?
Бхаргав

Якщо ви хочете все-таки зафіксувати вихід
підкрипту,

@Bhargav за цим посиланням stackoverflow.com/questions/14302389 / ...
tpbafk

16

Залежить від. Коротко ... Якщо ви хочете завантажити змінні на поточну консоль та виконати, ви можете використовувати source myshellfile.shу своєму коді. Приклад:

!#/bin/bash
set -x
echo "This is an example of run another INTO this session."
source my_lib_of_variables_and_functions.sh
echo "The function internal_function() is defined into my lib."
returned_value=internal_function()
echo $this_is_an_internal_variable

set +x

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

!#/bin/bash
set -x
./executing_only.sh
sh i_can_execute_this_way_too.sh
bash or_this_way.sh
set +x

Я сподіваюся, що вам допоможе. Дякую.


2
Зауважте, що sourceце особливість башма. Стандартна оболонка бура має лише .(наприклад . other_script.sh).
Мартін Турноїй

15

Ви можете використовувати /bin/shдля виклику або виконання іншого сценарію (за допомогою власного сценарію):

 # cat showdate.sh
 #!/bin/bash
 echo "Date is: `date`"

 # cat mainscript.sh
 #!/bin/bash
 echo "You are login as: `whoami`"
 echo "`/bin/sh ./showdate.sh`" # exact path for the script file

Вихід буде:

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013

1
Напевно це буде працювати showdate.shпід / bin / sh, а не / bin / bash?
Кріс Уоттс

Я спробував з " /bin/sh ./showdate.sh", " /bin/bash ./showdate.sh", " ./showdate.sh" і запустив файл: mainscript.sh і отримав такий же вихід.
Ранджіткумар T

10

Просто додайте в рядок все, що б ви набрали в терміналі для виконання сценарію!
наприклад:

#!bin/bash
./myscript.sh &

якщо сценарій, який потрібно виконати, не в одному каталозі, просто використовуйте повний шлях сценарію.
наприклад: `/ home / user / script-directory /./ myscript.sh &


@Carpetsmoker &для фонового завдання
Андрій Красуцький

9

Спочатку потрібно включити файл, який ви телефонуєте:

#!/bin/bash
. includes/included_file.sh

то ви називаєте свою функцію так:

#!/bin/bash
my_called_function


9

Якщо у вас в іншому каталозі є інший файл, ви можете:

bash another_script.sh

або

source another_script.sh

або

. another_script.sh

Якщо ви використовуєте bashзамість цього source, скрипт не може змінити середовище батьківського сценарію. .Команда стандарту POSIX , а sourceкоманда є більш читабельним Баш синонім .(я віддаю перевагу sourceбільш .). Якщо ваш скрипт проживає в іншому місці, просто вкажіть шлях до цього сценарію. Як відносний, так і повний шлях повинні працювати.


5

У верхній відповіді пропонується додати #!/bin/bashрядок до першого рядка викликаного підкрипту. Але навіть якщо ви додасте шебанг, набагато швидше * запустити скрипт у підколонці та захопити вихід:

$(source SCRIPT_NAME)

Це працює, коли ви хочете продовжувати працювати той самий інтерпретатор (наприклад, від bash до іншого скрипту bash) і гарантує, що рядок shebang підскрипту не виконується.

Наприклад:

#!/bin/bash
SUB_SCRIPT=$(mktemp)
echo "#!/bin/bash" > $SUB_SCRIPT
echo 'echo $1' >> $SUB_SCRIPT
chmod +x $SUB_SCRIPT
if [[ $1 == "--source" ]]; then
  for X in $(seq 100); do
    MODE=$(source $SUB_SCRIPT "source on")
  done
else
  for X in $(seq 100); do
    MODE=$($SUB_SCRIPT "source off")
  done
fi
echo $MODE
rm $SUB_SCRIPT

Вихід:

~ ❯❯❯ time ./test.sh
source off
./test.sh  0.15s user 0.16s system 87% cpu 0.360 total

~ ❯❯❯ time ./test.sh --source
source on
./test.sh --source  0.05s user 0.06s system 95% cpu 0.114 total

* Наприклад, коли на пристрої запущено вірус чи засоби захисту, для виконання нового процесу може знадобитися зайвих 100 мс.



4
 #!/bin/bash

 # Here you define the absolute path of your script

 scriptPath="/home/user/pathScript/"

 # Name of your script

 scriptName="myscript.sh"

 # Here you execute your script

 $scriptPath/$scriptName

 # Result of script execution

 result=$?

1
неправильне scriptPathім’я папки чи файлу scriptNameз пробілами
Андрій Красуцький

3

Припустимо, новий файл - "/ home / satya / app / app_specific_env", а вміст файлу наступний

#!bin/bash

export FAV_NUMBER="2211"

Додайте посилання цього файлу до файлу ~ / .bashrc

source /home/satya/app/app_specific_env

Коли ви перезавантажуєте машину чи переробляєтеся, спробуйте echo $FAV_NUMBERв терміналі. Це виведе значення.

На всякий випадок, якщо ви хочете побачити ефект відразу, source ~/.bashrcу командному рядку.


3
chmod a+x /path/to/file-to-be-executed

Це було єдине, що мені було потрібно. Після того, як сценарій для виконання буде виконаний таким чином, ви (принаймні в моєму випадку) не потребуєте жодної іншої додаткової операції, наприклад, shабо ./під час виклику сценарію.

Завдяки коментарю @Nathan Lilienthal


1

Існують деякі проблеми з імпортом функцій з іншого файлу.
По-перше : Вам не потрібно робити цей файл виконуваним. Краще не робити цього! просто додати

. file

імпортувати всі функції. І всі вони будуть наче визначені у вашому файлі.
По-друге : Ви можете визначити функцію з однойменною назвою. Це буде переписано. Це погано. Ви можете заявити так

declare -f new_function_name=old_function_name 

і тільки після цього робити імпорт. Таким чином, ви можете назвати стару функцію новим іменем.
По-третє : Ви можете імпортувати лише повний список функцій, визначених у файлі. Якщо деякі не потрібні, ви можете скасувати їх. Але якщо ви перезапишете свої функції після зняття, вони будуть втрачені. Але якщо ви встановите посилання на нього, як описано вище, ви можете відновити його після скасування з тим самим іменем.
НарештіЗагальна процедура імпорту небезпечна і не така проста. Будь обережний! Ви можете написати сценарій, щоб зробити це більш легким та безпечним. Якщо ви використовуєте лише частину функцій (не всі), краще розділіть їх на різні файли. На жаль, ця техніка не спрацювала добре. Наприклад, у python та деяких інших мовах скриптів це легко та безпечно. Можливе часткове імпортування лише необхідних функцій із власними іменами. Ми всі хочемо, щоб у наступних версіях куща був виконаний той самий функціонал. Але тепер ми повинні написати багато додаткової тріски, щоб робити те, що ти хочеш.


(Ласкаво просимо до SO!) Оскільки користувача Praveen востаннє бачили в 2011 році, важко буде розібратися, чи було питання, як змусити виконати оболонку a.sh виконувати b.sh (і продовжити виконання) a.sh, якщо ні заповів інакше ), або в буквальному сенсі виклику b.sh . (Моя перевірка орфографії не ловить bush versions.) (Чи є до кого звернутися, щоб допомогти вам з граматикою англійської мови? (Іноді хотілося б, щоб я).)
сіра борода

0

Використовуйте зворотній зв'язок.

$ ./script-that-consumes-argument.sh `sh script-that-produces-argument.sh`

Потім отримайте вихід сценарію виробника як аргумент на споживчому сценарії.

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