Как передавать данные через канал в утилиту/команду как часть оболочки здесь-doc?

Следующий пример представляет собой своего рода классический способ использования каналов. Справа от канала у нас есть «простая» утилита, которая считывает данные из стандартного ввода (канала) и выводит на стандартный вывод в обратном порядке:

{ cat <</EOF
Hello
World
/EOF
} | rev

Очевидно, что результат таков:

olleH
dlroW

Теперь я хочу передать эти данные через канал в команда/утилита, которая является частью оболочки here-doc:

{ cat <</EOF
Hello
World
/EOF
} | ksh -x <</EOF
rev
/EOF

Это не работает, нет сообщения об ошибке, ничего, переданные данные теряются, так как ksh перенаправляет stdin на here-doc.

Пробовал какое-то перенаправление:

set -x
{ cat <</EOF
Hello
World
/EOF
} | { exec 4<&0; ksh -x <</EOF; exec 0<&4 4<&-; }
rev <&4
/EOF

Но и это не работает, показывает ошибку по команде rev, очевидно перенаправление stdin на fd4 не передается подпроцессам ksh:

+ exec
+ 4<& 0
+ ksh -x
+ cat
+ 0<< \/EOF
rev <&4
/EOF
+ 0<< \/EOF
Hello
World
/EOF
+ rev
+ ksh[1]: 4: cannot open [Ungültiger Dateideskriptor]
+ exec
+ 0<& 4 4<& -

Я застрял здесь.

Мое реальное приложение намного сложнее: в левой части канала я выполняю ssh для исходного сервера, опционально sudo для другого пользователя на этом сервере и запускаю tar для передачи некоторых файлов данных. С правой стороны трубы мне нужно будет подключиться по ssh к целевому серверу, при желании sudo к другому пользователю и, наконец, запустить tar для получения данных из трубы.

Кстати: все работает нормально, если я НЕ использую here-doc в правой части канала:

{ cat <</EOF
Hello
World
/EOF
} | ksh -xc "rev"

Даже с ssh плюс sudo плюс tar это работает нормально. По какой-то причине я бы предпочел, чтобы документация по оболочке находилась справа. Как видите, ksh — моя любимая оболочка в этом приложении.

В соответствии с запросом: мое исходное утверждение похоже на

ssh $SSHOPT $INST_FILE_USER@$INST_FILE_HOST "cd $IDIR && { tar -cvf - $IFIL && echo RCSRC0 >&2 || echo RCSRC1 >&2; }" 2>$TMPFILE.err.src | ssh $SSHOPT $TRG_USER@$TRG_HOST "cd $TDIR && { tar -xmvf - && echo RCTRG0 || echo RCTRG1; }" 1>$TMPFILE.out.trg 2>&1

Пока все работает нормально. Как видите, реализован минимум проверки ошибок, что позволяет распознавать успех tar. Теперь я должен добавить функциональность sudo, это означает, что между оболочкой из ssh и командой cd я должен добавить некоторый код для переключения пользователя. Это действительно судо, которое будет использоваться? Это может быть команда pbrun, так как клиенты могут предпочесть pbrun. С этими различными сценариями можно справиться гораздо гибче, если вместо одного оператора-монстра будут использоваться здесь-документы.

Обновление от 21 мая: Я пытался следовать рекомендациям, данным до сих пор, но я все еще застрял. Давайте посмотрим на приведенный ниже ответ, который у меня работает нормально:

echo yup | ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
puy

Если я начну использовать ssh или использовать ssh в сочетании с sudo, мой пример с перенаправлением больше не работает:

echo yup | ssh admin@trg14 ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
bash: 4: Bad file descriptor

echo yup | ssh admin@trg14 sudo -n -u trg4 ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
bash: 4: Bad file descriptor

Я пробовал 2 сценария с Комбинация ssh и sudo: первая использует here-doc в качестве входных данных для ksh:

Сценарий 1:

echo yup | ssh admin@trg14 sudo -n -u trg4 -- ksh<</EOF
whoami && whoami && rev && whoami
/EOF
trg4
trg4
trg4

Это работает до сих пор. Примечание: все 4 команды запускаются от имени пользователя trg4, rev не получает никаких входных данных через канал, как ожидалось, из-за здесь-документа.

Поэтому я попытался реализовать решение, предложенное ниже: здесь-doc будет вводиться как параметр ksh:

Сценарий 2:

echo yup | ssh admin@trg14 sudo -n -u trg4 -- ksh -c "$(cat<</EOF
whoami && whoami && rev && whoami
/EOF
)"
trg4
admin
puy
admin

Вывод из rev соответствует ожидаемому, но: whoami показывает нам, что в этой версии/реализации только первая команда first запускается от имени пользователя sudo, остальные команды будут выполняться от имени пользователя ssh! В случае rev нет проблем, но если вам нужно получить доступ к файлам базы данных или записать их, у вас не будет проблем с разрешениями.

Вывод из этих двух примеров: сценарий 1 может быть правильным путем для запуска всех команд под правильным пользователем sudo, но для использования конвейера потребуется решение перенаправления стандартного ввода.

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

0
21.05.2019, 17:10
1 ответ

[вы должны задать другой вопрос о другой проблеме, вместо того, чтобы копаться в этом]

Запуск ssh с аргументом [команда] (s)

Когда вы запускаете sshс [command]аргументами, как в ssh user@host foo bar baz, происходит следующее: его аргументы будут объединены пробелами в один аргумент, который будет передан через -c] переключиться на оболочку входа пользователя на удаленной машине (, если эта оболочка /bin/sh, /bin/sh -c 'foo bar baz'будет запущена ).

Теперь, что происходит в вашем примере:

echo yup | ssh admin@trg14 ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'

заключается в том, что аргументы ssh будут объединены в строку:

ksh -c exec 4<&0; ksh -c "rev <&5" 5<&4

и сначала запустится оболочка на удаленной машине

ksh -c exec 4<&0

, а затем

ksh -c "rev <&5" 5<&4

как две отдельные команды, и конечно fd 4 во второй ни на что не указывает, потому что он был только перенаправлен в первой команде.

0
28.01.2020, 03:42

Теги

Похожие вопросы