возвращаемое значение оболочки bash - PullRequest
1 голос
/ 27 апреля 2019

Я пытаюсь выучить скрипты в Linux.У меня есть скрипт, и я хочу получить возвращаемое значение этого скрипта и сохранить его в переменной.

Любая помощь приветствуется.

Заранее спасибо.

#!/bin/bash
HOST_NAME=$1

{ echo "105" ; sleep 5; } | telnet $HOST_NAME 9761;

Ответы [ 4 ]

3 голосов
/ 27 апреля 2019

Чтобы избежать путаницы, не думайте / не говорите о нем как о возвращаемом значении, думайте о нем как о том, что это такое - статус выхода.

В большинстве языков программирования вы можете зафиксировать возвращаемое значение функции, записав все, что эта функция возвращает в переменную, например, с C-подобным языком:

int foo() {
    printf("35\n");
    return 7;
}

void main() {
    int var;
    var=foo();
}

переменная var в main() после вызова foo() будет содержать значение 7, и 35 будет напечатано в стандартный вывод. Однако в оболочке с похожим кодом:

foo() {
    printf "35\n"
    return 7
}

main() {
    local var
    var=$(foo)
}

var будет иметь значение 35, а неизменяемая встроенная переменная $? , которая всегда содержит состояние выхода последнего запуска команды , будет иметь значение 7. Если вы хотите продублировать поведение C, где 35 идет в стандартный вывод, а var содержит 7, тогда это будет:

foo() {
    printf "35\n"
    return 7
}

main() {
    local var
    foo
    var=$?
}

Тот факт, что функции оболочки используют ключевое слово return, чтобы сообщать о своем статусе выхода, сначала сбивает с толку, если вы привыкли к другим языкам на основе Алгола, таким как C, но если они использовали exit, то это приведет к завершению всего процесс, поэтому они должны были использовать что-то, и быстро становится очевидно, что это на самом деле означает.

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

Кстати, чтобы не усложнять ситуацию, я сказал выше, что $? - это переменная, но на самом деле это значение «специального параметра» ?. Если вы действительно хотите понять разницу сейчас, смотрите https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameters для обсуждения параметров оболочки, которые включают в себя «специальные параметры», такие как ? и #, «позиционные параметры», такие как 1 и * 1036. * и "переменные", такие как HOME и var, используемые в моем сценарии выше.

1 голос
/ 27 апреля 2019

Это зависит от того, что вы подразумеваете под возвращаемым значением .

Процессы (в UNIX-подобных системах) могут возвращать в оболочку один беззнаковый байт в качестве состояния выхода, что дает значение в диапазоне 0-255. По соглашению ноль означает успех, а любое другое значение означает сбой.

(В языках более низкого уровня, таких как C, вы можете получить больше, чем просто этот статус выхода, но это не отображается в bash).

Состояние завершения последнего запуска команды хранится в переменной ?, поэтому вы можете получить ее значение из $?, однако, поскольку многие программы возвращают только 0 (это работало) или 1 (это не работало) ), это не очень полезно.

Bash условия, такие как if и while проверка на успешность (код выхода 0) или неудача (код выхода ненулевой):

if some-command
then
    echo "It worked"
else
    echo "It didn't work"
fi

Однако ....

Если вы имеете в виду, что хотите получить вывод из сценария, это другое дело. Вы можете захватить его, используя:

var=$(some-command)

Но подождите, это захватывает только обычный вывод, направленный в поток с именем stdout (дескриптор файла 1), он не захватывает сообщения об ошибках, которые большинство программ записывают в поток с именем stderr (дескриптор файла 2). Для регистрации ошибок также необходимо перенаправить дескриптор файла 2 на дескриптор файла 1:

var=$(some-command 2>&1)

Выходной текст теперь находится в переменной var.

1 голос
/ 27 апреля 2019

Переменная оболочки $? хранит возвращаемое значение, однако с клиентом Linux telnet это может быть не так полезно, как вы думаете. Клиент возвратит 1, если удаленный хост закрывает соединение (или возникает какая-либо удаленная или сетевая ошибка), и 0, если локальная клиентская сторона успешно закрывает соединение. Проблема в том, что многие службы написаны так, что они отправляют данные, а затем сами закрывают TCP-соединение, не дожидаясь клиента:

$ telnet time-b.timefreq.bldrdoc.gov 13
Trying 132.163.96.2...
Connected to time-b-b.nist.gov.
Escape character is '^]'.

58600 19-04-27 13:56:16 50 0 0 736.0 UTC(NIST) *
Connection closed by foreign host.
$ echo $?
1

Даже если клиент отправляет серверу команду на выход через поток TCP, это все равно приводит к тому, что удаленная сторона закрывает соединение, с тем же результатом:

$ telnet mail.tardis.ed.ac.uk 25
Trying 193.62.81.50...
Connected to isolus.tardis.ed.ac.uk.
Escape character is '^]'.
220 isolus.tardis.ed.ac.uk ESMTP Postfix (Debian/GNU)
QUIT
221 2.0.0 Bye
Connection closed by foreign host.
$ echo $?
1

Итак, вы получите 1 независимо от того, что на самом деле. Если вы хотите вернуть значение удаленного скрипта, это проще сделать с ssh, например так:

$ ssh ssh.tardis.ed.ac.uk "exit 5"
THE TARDIS PROJECT  |  pubpubpubpubpubpubpubpubpub  |  Authorised access only
$ echo $?
5

Насколько я знаю, единственное время, когда telnet вернул бы ноль (т. Е. Успех), это если вы сбежите и получите клиент, например:

$ telnet www.google.com 80
Trying 216.58.210.36...
Connected to www.google.com.
Escape character is '^]'.
^]

telnet> quit
Connection closed.
$ echo $?
0

Надеюсь, это поможет.

0 голосов
/ 27 апреля 2019

В переменной ? всегда хранится код завершения предыдущей команды.

Вы можете получить значение с помощью $?.

Некоторый контекст: http://tldp.org/LDP/abs/html/exit-status.html

...