Существует обходной путь и простая загрузка (Linux Flavor )ISO. Вы можете использовать Live Flavor любой ОС Linux, такой как CentOS, Kali Linux, Ubuntu и т. д....
Why is this happening?
Это cat
, которое необходимо завершить до того, как оболочка доберется до echo
. Это «блокировка навсегда», потому что cat
живет.
Is there a workaround?
В Bash я бы использовал подстановку процесса для запуска cat
, который не блокируется. Когда cat
убрано, легко echo OK
, только если все действительно в порядке (с &&
или$?
). Пример:
ssh -f … > >(cat -A) 2>&1 && echo OK; echo "The script goes on."
Теперь cat
работает до и после того, как ssh
переходит в фоновый режим, но сценарий продолжается, как только ssh
это делает (или как только ssh
дает сбой без перехода в фоновый режим ).
Когда ssh -f
«переходит в фоновый режим» после подключения и аутентификации на хосте, он будет продолжать удерживать открытые дескрипторы своих исходных stdin, stdout и stderr, поэтому, если эти дескрипторы были подключены через каналы к другим процессам (, так как его stdout + stderr в вашем примере для cat -A
), это будет иметь эффект сохранения этих процессов, даже если они больше не нужны.
ssh
демонизирует себя, вызывая библиотечную функцию daemon(3)
, но вызывает ее с помощью noclose = 1
, предотвращая перенаправление stdin/stderr/stdout из /dev/null
.
Это было частично исправлено в последних версияхopenssh
(для основного процесса управления --стандартного ввода и стандартного вывода в 2010 , стандартного вывода в 2016 ; для процесса сеанса --стандартный вывод в 2017 ), но если вам нужно запустить более старый ssh или вам нужно, чтобы он также перестал цепляться за стандартный вывод, единственным «решением» может быть использование LD_PRELOAD
хак, который переопределяет функцию daemon(3)
оболочкой, которая вызывает оригинал с помощью noclose = 0
.
$ cat daemon-force-close.c
#define _GNU_SOURCE
#include <unistd.h>
#include <dlfcn.h>
#include <err.h>
int daemon(int nochdir, int noclose){
static int (*orig)(int, int);
if(!orig && !(*(void**)&orig = dlsym(RTLD_NEXT, "daemon")))
errx(1, "%s", dlerror());
return orig(nochdir, 0);
}
$ cc -shared -Wall -O2 daemon-force-close.c -ldl -o daemon-force-close.so
$ LD_PRELOAD=./daemon-force-close.so \
ssh -Nf dummy@localhost -MS./ctlsock 2>&1 | cat -A
dummy@localhost's password:
$
[no Ctrl-C needed]
$ ssh -S ~/w/c/ctlsock dummy@localhost
Last login: Tue May 28 21:04:26 2019 from ::1
...