it-swarm.com.ru

Как вызвать скрипт Shell из другого скрипта Shell?

У меня есть два сценария оболочки, a.sh и b.sh.

Как я могу вызвать b.sh из скрипта оболочки a.sh?

560
Praveen

Есть несколько способов сделать это:

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

  2. Или вызовите его с помощью команды source (псевдоним .), например: source /path/to/script;

  3. Или используйте команду bash для ее выполнения: /bin/bash /path/to/script;

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

Во втором методе, если вы используете exit во втором скрипте, он также выйдет из первого скрипта. Что не произойдет в первом и третьем способах.

742
Some programmer dude

Проверь это.

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

Есть несколько способов сделать это. Терминал для выполнения скрипта:

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

Все это правильно для пути с пробелами !!!

75
Andrei Krasutski

Ответ, который я искал:

( exec "path/to/script" )

Как уже упоминалось, exec заменяет оболочку без создания нового процесса. Однако , мы можем поместить это в подоболочку, что делается с помощью парантезов. 

Правка: На самом деле ( "path/to/script" ) достаточно.

51
Maxim Chetrusca

Вы можете использовать /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
14
Ranjithkumar T

Зависит от . Кратко ... Если вы хотите загрузить переменные на текущей консоли и выполнить, вы можете использовать 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

Я надеюсь, что поможет вам .... Спасибо.

14
Douglas Bonafé

Просто добавьте в строку все, что вы набрали бы в терминале, чтобы выполнить скрипт!
например.:

#!bin/bash
./myscript.sh &

если скрипт, который нужно выполнить, не находится в той же директории, просто используйте полный путь скрипта.
Например ::`/home/user/script-directory/./myscript.sh &

9
Anon

Простой источник поможет вам . Например.

#!/bin/bash
echo "My Shell_1"
source my_script1.sh
echo "Back in Shell_1"
7
Nitin Jawarkar

Сначала вы должны включить файл, который вы называете:

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

тогда вы вызываете свою функцию так:

#!/bin/bash
my_called_function
7
Ghazi Triki
pathToShell="/home/praveen/"   
chmod a+x $pathToShell"myShell.sh"
sh $pathToShell"myShell.sh"
4
Abdennour TOUMI
 #!/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=$?
4
Valero

Предположим, что новый файл "/ 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
Satya Kalluri
chmod a+x /path/to/file-to-be-executed

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

Благодаря комментарию @Nathan Lilienthal 

2
Asqan

Используйте backticks.

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

Затем извлеките выходные данные сценария производителя в качестве аргумента сценария потребителя.

1
David Cabrera

Верхний ответ предполагает добавление строки #!/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 мс.

1
cmcginty

Есть проблемы с импортом функций из другого файла.
Первый : Вам не нужно делать этот файл исполняемым. Лучше не делать этого! Просто добавьте 

. file

импортировать все функции. И все они будут, как если бы они были определены в вашем файле.
Второй : Вы можете определить функцию с тем же именем. Это будет перезаписано. Это плохо. Вы можете заявить, что так

declare -f new_function_name=old_function_name 

и только после этого выполните импорт . Таким образом, вы можете вызывать старую функцию под новым именем.
Третий : Вы можете импортировать только полный список функций, определенных в файле . Если некоторые из них не нужны, вы можете отменить их. Но если вы переписываете свои функции после сброса, они будут потеряны. Но если вы установите ссылку на него, как описано выше, вы можете восстановить после сброса с тем же именем.
Наконец В общем процедура импорта ввоза опасна и не так проста. Быть осторожен! Вы можете написать скрипт, чтобы сделать это более простым и безопасным .. Если вы используете только часть функций (не все), лучше разбейте их на разные файлы. К сожалению, эта техника не очень хорошо работает в Bash. Например, в python и некоторых других языках сценариев это просто и безопасно. Возможен частичный импорт только необходимых функций со своими именами. Мы все хотим, чтобы в следующих версиях куста была сделана та же функциональность. Но теперь мы должны написать много дополнительных кодов, чтобы делать то, что вы хотите. 

0
Anatoly