Он документирован (для POSIX) в Разделе 2.9.1 Простые команды базовой спецификации The Open Group. Там много текста; я обращаю ваше внимание на последний абзац:
Если есть имя команды, выполнение должно продолжаться, как описано в Поиск и выполнение команды. Если имя команды отсутствует, но команда содержит подстановку команды, команда завершается со статусом выхода последней выполненной подстановки команды. В противном случае команда завершается с нулевым статусом выхода.
Так, например,
Command Exit Status
$ FOO=BAR 0 (but see also the note from icarus, below)
$ FOO=$(bar) Exit status from "bar"
$ FOO=$(bar) baz Exit status from "baz"
$ foo $(bar) Exit status from "foo"
Так работает и bash. Но см. также раздел "Не все так просто" в конце.
phk, в своем вопросе Назначения подобны командам со статусом выхода, за исключением случаев, когда происходит замена команды?, предлагает
... кажется, что задание само по себе считается командой... с нулевым значением выхода, но которая применяется перед правой частью присваивания (например, вызов подстановки команды...)
Это не такой уж ужасный способ взглянуть на это.
Грубая схема для определения статуса возврата простой команды
(не содержащей ;
, &
, |
, &&
или ||
) такова:
$(...)
-
возьмите статус выхода из этой команды. Статус возврата для строки - последний встреченный номер.
Замены команд как аргументы к команде,
например, foo $(bar)
, не считаются; вы получаете статус выхода из foo
.
Перефразируя нотацию phk, поведение здесь такое
temporary_variable = EXECUTE("bar" )
overall_exit_status = EXECUTE("foo", temporary_variable )
Но это небольшое упрощение. Общий статус возврата из
A=$(cmd1) B=$(cmd2) C=$(cmd3) D=$(cmd4) E=mc2
- это статус выхода из cmd4
.
Присвоение E=
, которое происходит после присваивания D=
не устанавливает общий статус выхода в 0.
icarus, в своем ответе на вопрос phk, поднимает важный вопрос: переменные могут быть установлены как readonly. Предпоследний абзац в Разделе 2.9.1 стандарта POSIX гласит:
Если любое из присваиваний переменной пытается присвоить значение переменной для которой в текущей среде оболочки установлен атрибут readonly (независимо от того, выполняется ли присвоение в этом окружении), произойдет ошибка присвоения переменной. Последствия этих ошибок см. в Последствия ошибок оболочки.
поэтому, если вы скажете
readonly A
C=Garfield A=Felix T=Tigger
что статус возврата равен 1.
Не имеет значения, если строки Garfield
, Felix
, и/или Tigger
заменяются командными подстановками - но см. примечания ниже.
Раздел 2.8.1 Последствия ошибок оболочки содержит еще одну кучу текста, и таблица, и заканчивается
Во всех случаях, показанных в таблице. когда от интерактивной оболочки требуется не завершать работу, оболочка не должна выполнять дальнейшую обработку команды, в которой произошла ошибка.
Некоторые детали имеют смысл, некоторые нет:
A=
иногда прерывает командную строку,
как, по-видимому, указано в последнем предложении.
В приведенном выше примере C
установлено на Garfield
, но T
не установлено.
(и, конечно, не задан A
). C=$(cmd1) A=$(cmd2) T=$(cmd3)
выполняет cmd1
но не cmd3
. cmd2
.
(Кстати, это еще больше подрывает интерпретацию phk о том.
что значение выхода из присваивания применяется
перед правой частью присваивания.)В моих версиях bash,
readonly A C=something A=something T=something cmd0
does execute cmd0
.
В частности,
C=$(cmd1) A=$(cmd2) T=$(cmd3) cmd0
выполняет cmd1
и cmd3
но не cmd2
.
(Обратите внимание, что это противоположно его поведению при отсутствии команды).
И он устанавливает T
(а также C
) в окружение
cmd0
.
Интересно, не является ли это ошибкой в bash?
В первом абзаце этого ответа говорится о "простых командах". В спецификации сказано:
"Простая команда" - это последовательность необязательных назначений переменных и перенаправлений, в любой последовательности, за которой по желанию следуют слова и перенаправления, завершается оператором управления.
Это утверждения, подобные тем, что приведены в моем первом блоке примеров:
$ FOO=BAR
$ FOO=$(bar)
$ FOO=$(bar) baz
$ foo $(bar)
первые три из них включают присваивание переменных, а последние три включают подстановки команд.
Но некоторые присваивания переменных не так просты. bash(1) говорит:
Операторы присваивания могут также появляться в качестве аргументов для
alias
,declare
,typeset
,export
,readonly
, иlocal
встроенные команды (команды declaration).
Для export
, спецификация POSIX гласит:
EXIT STATUS
0
Все операнды имен были успешно экспортированы.
>0По крайней мере одно имя не удалось экспортировать, или была указана опция
-p
и произошла ошибка.
И POSIX не поддерживает local
, но bash(1) говорит:
Ошибкой является использование
local
не внутри функции. Статус возврата равен 0, еслиlocal
не используется вне функции, или имя является недопустимым, или имя является переменной, доступной только для чтения.
Читая между строк, мы видим, что такие команды декларации, как
export FOO=$(bar)
и
local FOO=$(bar)
больше похожи на
foo $(bar)
постольку, поскольку они игнорируют статус выхода из bar
и выдают статус выхода, основанный на главной команде
(export
, local
или foo
).
Таким образом, мы имеем странности вроде
Command Exit Status
$ FOO=$(bar) Exit status from "bar"
(unless FOO is readonly)
$ export FOO=$(bar) 0 (unless FOO is readonly,
or other error from “export”)
$ local FOO=$(bar) 0 (unless FOO is readonly,
statement is not in a function,
or other error from “local”)
которые мы можем продемонстрировать с помощью
$ export FRIDAY=$(date -d tomorrow)
$ echo "FRIDAY = $FRIDAY, status = $?"
FRIDAY = Fri, May 04, 2018 8:58:30 PM, status = 0
$ export SATURDAY=$(date -d "day after tomorrow")
date: invalid date ‘day after tomorrow’
$ echo "SATURDAY = $SATURDAY, status = $?"
SATURDAY = , status = 0
и
myfunc() {
local x=$(echo "Foo"; true); echo "x = $x -> $?"
local y=$(echo "Bar"; false); echo "y = $y -> $?"
echo -n "BUT! "
local z; z=$(echo "Baz"; false); echo "z = $z -> $?"
}
$ myfunc
x = Foo -> 0
y = Bar -> 0
BUT! z = Baz -> 1
К счастью, ShellCheck отлавливает ошибку и поднимает SC2155, который советует изменить
export foo="$(mycmd)"
на
foo=$(mycmd)
export foo
и
local foo="$(mycmd)"
на
local foo
foo=$(mycmd)
Он может находиться только в памяти и не подлежит восстановлению, и в этом случае вам придется попытаться восстановить его из файловой системы с помощью одного из этих инструментов восстановления файловой системы. (или, может быть, по памяти). Тем не мение!
$ cat hamlet.c
#include <unistd.h>
int main(void) { while (1) { sleep(9999); } }
$ gcc -o hamlet hamlet.c
$ md5sum hamlet
30558ea86c0eb864e25f5411f2480129 hamlet
$ ./hamlet &
[1] 2137
$ rm hamlet
$ cat /proc/2137/exe > newhamlet
$ md5sum newhamlet
30558ea86c0eb864e25f5411f2480129 newhamlet
$
С интерпретируемыми программами получение файла сценария может быть где-то между сложным и невозможным, поскольку / proc / $$ / exe
будет указывать на perl
или что-то еще, а входной файл возможно, уже были закрыты:
$ echo sleep 9999 > x
$ perl x &
[1] 16439
$ rm x
$ readlink /proc/16439/exe
/usr/bin/perl
$ ls /proc/16439/fd
0 1 2
Открыты только стандартные файловые дескрипторы, поэтому x
уже исчез (хотя может еще какое-то время существовать в файловой системе, и кто знает, что интерпретатор хранит в памяти) .
Dijiste que es C++, por lo que debería ser posible volcarlo de la memoria.
Primero desea encontrar el proceso en la memoria:
$ cat /proc/[pid]/maps
00400000-00404000 r-xp 00000000 ca:01 16823 /home/ec2-user/a.out (deleted)
Entonces puedes volcarlo
$ gdb --pid [pid]
dump memory /home/ec2-user/output 0x00400000 0x00404000
Entonces debería poder ejecutarlo marcándolo como ejecutable(chmod +x
)
$ file output
output: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, missing section headers