Я бы лучше скопировал хотя бы myProgramInputFile
(как и метод 3 ); Я думаю, что это будет более надежным. Однако, есть способ заставить его работать с единственным методом 1.
Мой подход
Я советую вам сделать (локальный) скрипт, который копирует соответствующий файл на удаленную сторону, запускает выполнение и очищает впоследствии.
Нам понадобятся три локальных файла: myLocalScript
(исполняемый файл), myRemoteScript
и myProgramInputFile
.
Содержание myLocalScript
:
#!/bin/bash
# step 1: storing command line arguments to meaningful names
ssh_command="ssh $1"
script="$2"
input="$3"
# step 2: creating remote temporary file
remote_input=$($ssh_command 'mktemp')
# step 3: copying the content of local input file to the remote temporary file
cat "$input" | $ssh_command "cat > \"$remote_input\""
# step 4: sourcing the script to the remote side
$ssh_command "input=\"$remote_input\" bash -s" < "$script"
# step 5: removing the remote temporary file
$ssh_command "rm \"$remote_input\""
myRemoteScript
будет выглядеть так:
# shebang is not needed, this script will effectively be sourced
# Do stuff…
myProgram input "$input"
# Do more stuff…
Файлы myProgramInputFile
(локальный) и myProgram
(удаленный) останутся такими же, как в текущих настройках.
Местное использование:
./myLocalScript <username>@<hostname> myRemoteScript myProgramInputFile
Технические примечания и объяснения:
- На шаге 2
mktemp
создает файл во временном каталоге на удаленном компьютере. Мы не хотим использовать mktemp -u
чтобы избежать ситуации, когда кто-то еще создает файл с таким же именем между нашими шагами 2 и 3.
- На шаге 3 мы могли бы использовать
scp
если бы использовали mktemp -u
. Удаленный временный файл уже существует, поэтому мы используем cat
для записи в него.
- На шаге 4
myRemoteScript
должен знать путь к временному файлу в контексте удаленного компьютера. Вот почему мы передаем наш локальный $remote_input
качестве input
переменной удаленному bash
. Таким образом, когда myRemoteScript
подается в упомянутый bash
, $input
в нем указывает путь к временному файлу.
- Если мы сломаем удаленный
bash
(скажем, одним нажатием Ctrl + c), myLocalScript
перейдет к шагу 5 и все равно выполнит очистку. Это причина, по которой очистка не заканчивается в myRemoteScript
, хотя это может быть.
Единственный метод 1 подход
Благодаря Here Documents вы можете встроить myProgramInputFile
в myShellScript
.
Это будет легко, если myProgramInputFile
представляет собой текстовый файл и myProgram
может читать стандартный stdin
(возможно, с myProgram input -
синтаксис? или может быть, когда input
опущен?)
myShellScript
будет выглядеть так:
# shebang is not needed, this script will effectively be sourced
# Do stuff…
myProgram input - <<"EOF"
The content of myProgramInputFile is pasted here,
it continues here
and here,
and so on.
EOF
# Do more stuff…
Затем мы запустим его, как в методе 1:
ssh <username>@<hostname> 'bash -s' < myShellScript
Если myProgram
не может прочитать стандартный stdin
но удаленная система позволяет вам использовать /proc/self/
тогда мы должны написать ключевую строку в myShellScript
следующим образом:
myProgram input /proc/self/fd/0 <<"EOF"
Если myProgramInputFile
больше, чем текст, то мы должны кодировать его локально (см. uuencode
, base64
) и декодировать на удаленной стороне. Мы также должны проверить, нет ли строки EOF
в закодированном тексте, измените разделитель документа здесь, если так. Обратите внимание, что base64
не использует _
поэтому E_O_F
в этом случае совершенно безопасен (но, может быть, не с uuencode
, я не знаю).
В качестве подтверждения концепции я распаковал значок Super User, закодировал его с помощью base64
и встроил в скрипт. Я решил продемонстрировать подход /proc/self/fd/0
с помощью cp
но это также может быть cat > ~/SUfavicon.ico
; или лучше gzip -cd > ~/SUfavicon.ico
ранее в трубе.
И, конечно, в вашем случае вместо myProgram
будет cp
.
Обратите внимание, что в этом случае {}
важны, они делают документ здесь направленным на base64 -d
.
# shebang is not needed, this script will effectively be sourced
{ base64 -d | gzip -cd | cp /proc/self/fd/0 ~/SUfavicon.ico ; } <<"E_O_F"
H4sICE3cXFkCA2Zhdmljb24uaWNvAO2XT2jTUBzHf2lnO1HXIAiKYHuSIYhzoCgIlV1EdtDDTmMg
CIKI7DQ9Taq71Il0VfBSmP9QmKziYRd3GCoqu40JIhtiB7sIOm1AcJ1r8/y+5bXEZ1KbtH07uMCH
3/pLvvm8lzYvC5FGAdJ1Qo3R+RaivUQUi1mfx9BPodeOns77ZPXXthZy25IgX2bbZkrz5uIjmvz+
lPKCBZAEmkOeH8/ABOjXt1AXb86NUg+Ov/AtSwOoy6gl1PYq+UtuA0RuHjCw32d+Dn6znrzwH/SZ
fy78w6gBr3lkOpH9DPg53nrNLzykVpzjDp8DatFLfrCXArkHlBLzfwcOgUANed4zE320/es4fRDz
7/Zw/XiP3TxHm5bGK9f/mJ/rv5StfP++8sjmxLU/7DWP7FHkiqhfUNuq5J+AM7h/jvDm/F06geOv
AJ5bBX0uwyvnTV5x/2bE/fsGmQK8U6hdTsGhsMXItI3XNq5hPQlbVPZjtRiKgKi1zvDV5bh9ndH/
9jDG/iCi6yuAVaOcXczuYy78ALPgOtjhND/Za/OzBvjtfARb19HP6a3Dr5GHDS4NvJL8g3795GOD
77bkv6rYn97w/9f+Ecl/Q7G/X/K/B0GF/t1gRRpDBoRU+MUYLjusgznR39lsvxjDAFh2GMdPFX4x
hrNOzwQF178NPHNwl8BEk39//Bk06eC9BfY06veH/Z1gFNwHKRAW/pMO8+5p9P2H/Wnp+A7hT0ru
qWasP1X88vqbbpL/FJgBs+AF0FX6PTx/Nvzr6x9W7B+T/BdV+fm7BshL/g6F/ozknq7z/Uur0bsL
PJbcv8ABRe9/Jekz///ntNt4m/z+N+M27xr8qz79n8A90M2fv//6vso+I0QJEF8jYcQNVnAjCiIG
KwYNZgIWtP4uhA2zNQriFRzz/NwwJF5yHzNCGgiy3wHSerE2FQAA
E_O_F
Запустите его как раньше:
ssh <username>@<hostname> 'bash -s' < myShellScript
Затем вы найдете ~/SUfavicon.ico
на удаленной машине.