Как использовать SSH для запуска локального сценария оболочки на удаленном компьютере?

Мне нужно запустить локальный сценарий оболочки (Windows / Linux) на удаленном компьютере.

У меня настроен SSH как на машине A, так и на машине B. Мой сценарий находится на машине A, которая будет запускать часть моего кода на удаленной машине, машине B.

Локальные и удаленные компьютеры могут быть системами на базе Windows или Unix.

Есть ли способ запустить это с помощью plink / ssh?


person Community    schedule 20.11.2008    source источник
comment
Тот же вопрос уже есть в serverfault: serverfault.com/questions/215756/ Так что, вероятно, нет смысла переносить этот вопрос.   -  person sleske    schedule 11.09.2012
comment
Однако на вопрос о сбое сервера ответов не так много. Может быть, этот вопрос должен заменить тот.   -  person Big McLargeHuge    schedule 18.12.2013
comment
Мне лично нравится этот ответ: unix.stackexchange.com/questions/87405/   -  person mikevoermans    schedule 09.07.2014
comment
Кроме того, очевидно, что это должно быть по теме, поскольку ssh - это основной инструмент для разработки программного обеспечения.   -  person static_rtti    schedule 31.08.2015
comment
@tripleee, спасибо, что напомнили мне о повторном голосовании.   -  person static_rtti    schedule 08.03.2017
comment
Вопросы о кофе и ssh не имеют одинаковой степени несоответствия теме SO. Проголосовали за повторное открытие.   -  person Vincent Cantin    schedule 22.11.2017
comment
кто-нибудь может прокомментировать тег ENDSSH, пожалуйста?   -  person bonobo    schedule 08.01.2018
comment
@ adam-Lear, я думаю, этот вопрос нужно открыть. Я изменил вопрос, чтобы он соответствовал stackoverflow. Самый популярный ответ здесь на самом деле не работает, если вы пытаетесь запустить локальный скрипт на удаленном компьютере Widows и если он имеет несколько строк. Я нашел способ и хотел бы предложить решение. Несмотря на то, что существует еще один пост о serverfault, из-за популярности этого вопроса большинство людей собираются приходить сюда ... поэтому убедитесь, что этот вопрос актуален, будет очень полезно для посетителей.   -  person alpha_989    schedule 20.04.2018
comment
@ alpha_989 Это честно. Я закрыл этот вопрос в одностороннем порядке за два месяца работы модератором сообщества. Это не тот холм, на котором я бы хотел умереть сейчас. :) Я открою снова, хотя это не гарантия, что он останется открытым, если сообщество в целом не согласится. Если он снова закроется, я предлагаю обсудить его в Meta Stack Overflow.   -  person Adam Lear    schedule 20.04.2018


Ответы (19)


Если компьютер A является компьютером с Windows, вы можете использовать Plink (часть PuTTY) с параметром -m, и он выполнит локальный сценарий на удаленном сервере.

plink root@MachineB -m local_script.sh

Если Машина A является системой на основе Unix, вы можете использовать:

ssh root@MachineB 'bash -s' < local_script.sh

Вам не нужно копировать сценарий на удаленный сервер для его запуска.

person Jason R. Coombs    schedule 28.04.2010
comment
есть ли преимущество в использовании опции -s? эта страница руководства наводит меня на мысль, что он будет обрабатывать стандартный ввод, когда завершится обработка параметров независимо от того, используется -s или нет. - person aeroNotAuto; 18.11.2011
comment
@ asia1281 Нет преимущества; Я выбрал эту технику, поскольку она казалась более ясной. Вероятно, безопасно опустить "-ки". - person Jason R. Coombs; 21.11.2011
comment
Для сценария, для которого требуется sudo, запустите ssh root@MachineB 'echo "rootpass" | sudo -Sv && bash -s' < local_script.sh. - person bradley.ayers; 21.09.2012
comment
@ bradley.ayers не забудьте начать команду с пробела, чтобы пропустить историю (P.S. вам нужно иметь HISTCONTROL=ignoreboth or ignorespace, чтобы она работала) - person derenio; 23.06.2013
comment
@ bradley.ayers, в каких ситуациях вам понадобится sudo, если вы уже входите в систему как root? - person Brian Schlenker; 21.01.2014
comment
@Agostino, вы можете добавить такие параметры: ssh root@MachineB ARG1="arg1" ARG2="arg2" 'bash -s' < local_script.sh Кредиты полностью переходят к ответу @chubbsondubs ниже. - person Yves Van Broekhoven; 07.03.2014
comment
Кажется, переменная окружения $ PATH не применяется? - person Qian Chen; 02.02.2015
comment
@ElgsQianChen Я не понимаю, о чем вы спрашиваете. Вы хотите, чтобы путь от локальной машины применялся к удаленной машине? Или вы хотите, чтобы какой-то PATH, который обычно присутствует на удаленной машине, был принят? В любом случае, что вам нужно сделать, так это определить, где установлен этот PATH, почему вы ожидаете, что он будет установлен при выполнении удаленной команды и где ваши ожидания нарушены, что лучше всего было бы решить в отдельном вопросе. - person Jason R. Coombs; 04.02.2015
comment
Я хочу, чтобы на удаленном компьютере был установлен $ PATH. Наконец, мне нравится решение добавить операторы экспорта в начало ~ / .bashrc. - person Qian Chen; 05.02.2015
comment
@SpencerBoucher Я не думаю, что это возможно. По крайней мере, в случае Unix, stdin на локальном компьютере уже обрабатывает поток сценария. Я предлагаю опубликовать отдельный вопрос и подробно рассказать о том, чего вы пытаетесь достичь. - person Jason R. Coombs; 01.04.2015
comment
Вышеупомянутые методы не работают для меня, если мне нужно выполнить локальный файл sh на удаленном компьютере, который требует файла pem для аутентификации. - person Praveen Pandey; 14.07.2016
comment
Шутка шутка: что будет, если у вас будет в local_script.sh ssh root @ MachineB 'bash -s' ‹local_script.sh;) - person talsibony; 19.08.2016
comment
@ JasonR.Coombs .. Я пытаюсь запустить файл .bat (похожий на local_scrip.sh) на машине Windows с вашей точной командой. Однако я обнаружил, что если файл .bat имеет более одной строки, вторая строка не выполняется. Вы нашли это правдой? - person alpha_989; 19.04.2018
comment
@ alpha_989: Прошло очень много времени с тех пор, как я пробовал работать на SSH-сервере в Windows. Я подозреваю, что это дефект или ограничение вашего SSH-сервера в Windows, что он не принимает более одной строки ввода от команды SSH при запуске в неинтерактивном режиме. Я предлагаю создать новый вопрос и точно описать, какой сервер и клиент вы используете, чего вы ожидаете и что получаете взамен. - person Jason R. Coombs; 20.04.2018
comment
да .. Я понял это, но не смог опубликовать здесь ответ, так как этот вопрос кажется закрытым: serverfault.com/a/ 908587/443721 - person alpha_989; 20.04.2018
comment
Небольшое примечание: используйте параметр --login, чтобы bash вел себя как обычная оболочка входа в систему (например, пути устанавливаются так, как указано в ~/.bash-profile и т. Д.). Используйте это как ssh root@MachineB 'bash -ls' < local_script.sh - person zoma; 10.05.2018
comment
@YvesVanBroekhoven Это устарело, но суть -s в том, чтобы иметь возможность передавать аргументы сценарию, полученному через stdin: ssh root@MachineB 'bash -s arg1 arg2' < local_script.sh. Если пропустить -s, arg1 будет интерпретироваться как удаленный сценарий, выполняемый с arg2 в качестве первого аргумента. Нет необходимости использовать переменные среды. - person JoL; 31.08.2018
comment
Этот ответ должен быть принятым ответом и быть поверх всех остальных. Это единственный вариант, который точно соответствует задаче, он короткий и легкий. Мне пришлось бороться около часа, рассматривая все остальные, пока я не увидел это. - person papillon; 07.01.2020
comment
Используется следующее, чтобы предоставить пароль извне и не отображать запрос по умолчанию: echo "password" | ssh user@server 'sudo --prompt="" --stdin bash -s' < local.sh - person nkmol; 10.02.2021
comment
Можно ли расширить эту возможность, запустив пример local_script.sh через бастион? - person openCivilisation; 27.02.2021
comment
Это работает для использования бастиона: ssh -o ProxyCommand="ssh $host1 -W %h:%p" $host2 "bash -s" < local.sh - person openCivilisation; 27.02.2021
comment
при такой пересылке стандартного ввода-вывода он зашифрован? например, если мы передадим "secret=var bash -s" < local.sh, это безопасно? - person openCivilisation; 27.02.2021
comment
Это, вероятно, заслуживает отдельного вопроса. - person Jason R. Coombs; 03.03.2021

Это старый вопрос, и ответ Джейсона работает нормально, но я хотел бы добавить следующее:

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

Это также можно использовать с su и командами, требующими ввода данных пользователем. (обратите внимание на ' сбежавший heredoc)

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

Вы можете вкладывать команды с этим синтаксисом, и это единственный способ, которым вложение работает (разумным способом)

ssh user@host <<'ENDSSH'
#commands to run on remote host
ssh user@host2 <<'END2'
# Another bunch of commands on another host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

Вы действительно можете общаться с некоторыми службами, такими как telnet, ftp и т. Д. Но помните, что heredoc просто отправляет stdin как текст, он не ждет ответа между строками

Изменить: я только что узнал, что вы можете сделать отступ внутри с помощью вкладок, если вы используете <<-END!

ssh user@host <<-'ENDSSH'
    #commands to run on remote host
    ssh user@host2 <<-'END2'
        # Another bunch of commands on another host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(Я думаю, это должно сработать)

См. Также http://tldp.org/LDP/abs/html/here-docs.html

person Yarek T    schedule 06.10.2010
comment
вы можете немного подождать, добавив такие строки, как: # $ (sleep 5) - person Olivier Dulac; 22.02.2013
comment
обратите внимание, что если заключить терминатор в одинарные кавычки (<<'ENDSSH'), строки не будут расширены, переменные не будут оцениваться. Вы также можете использовать <<ENDSSH или <<"ENDSSH", если хотите расширения. - person maackle; 18.06.2013
comment
Expect можно использовать, когда вам нужно автоматизировать интерактивные команды, такие как FTP. - person programaths; 14.04.2014
comment
Как теперь отправить HEREDOC на удаленный хост через SSH из сценария оболочки локально? - person krb686; 03.03.2015
comment
Обратите внимание, что у меня было Pseudo-terminal will not be allocated because stdin is not a terminal. сообщение. Чтобы этого избежать, нужно использовать ssh с -t -t параметрами. См. Этот поток на SO - person Buzut; 01.04.2016
comment
Эта опция не сработала для меня, поскольку каждая строка выполнялась так, как если бы вызывалась с помощью ssh user @ server 'line', в то время как мне требовалось, чтобы все строки выполнялись в одной среде. С ответом Джейсона все работает по мере необходимости. - person ivan_onys; 08.04.2016
comment
Если вы пытаетесь использовать синтаксис ‹< - 'END', убедитесь, что конечный разделитель heredoc имеет отступ с помощью TAB, а не пробелов. Обратите внимание, что копирование / вставка из stackexchange даст вам пробелы. Измените их на вкладки, и функция отступа должна работать. - person fbicknel; 24.06.2016
comment
Я проголосовал за это, и мой голос был засчитан как голос против .... странно, теперь я не могу это изменить - person sites; 01.07.2016
comment
Если пароль запрашивается во время входа в систему ssh, все команды будут выдаваться и интерпретироваться как ввод. - person Ben Affleck; 05.01.2017
comment
если я использую ‹< ENDSSH (без кавычек). и внутри выполнения команды, которая использует переменные awk, скажем, NR. как мне избежать переменной NR. \ NR не работает - person Sachin Sharma; 27.02.2017
comment
В MacOS ENDSSH, ENDFTP и т. Д. Должны быть записаны в начале строки. В противном случае будет выведено предупреждение -bash: line 3: ENDSSH: command not found. - person LoranceChen; 03.07.2017
comment
Большое спасибо Lorance Chen за вашу информацию о различиях в MacOS - у меня сейчас была эта проблема, поэтому я думаю, что ее следует добавить в @Yarek T - person kris_IV; 23.02.2019
comment
Единственное, что я могу критиковать в этом ответе, - это его ссылка на документацию ABS - вся причина, по которой Wooledge BashGuide было написано, чтобы иметь что-то менее пронизанное примерами плохой практики, чем ABS, заставляя нас, жителей IRC-канала freenode #bash, помогать людям избавляться от вредных привычек, которые они там приобрели. - person Charles Duffy; 29.01.2020
comment
Heredocs хороши, но стоит упомянуть, что этот метод работает, если вы знаете оболочку учетных записей или используете только синтаксис POSIX. Если вы не уверены, добавление bash -s перед сценарием будет безопаснее. - person Mig; 30.07.2020
comment
@maackle Неверно говорить, что <<"ENDSSH" можно использовать, если вы хотите расширения. Расширения не будут происходить в HEREDOC, если заключена в кавычки какая-либо часть слова, представляющего разделитель. - person Robin A. Meade; 05.03.2021

Кроме того, не забудьте экранировать переменные, если вы хотите забрать их с целевого хоста.

Это поймало меня в прошлом.

Например:

user@host> ssh user2@host2 "echo \$HOME"

распечатывает / home / user2

в то время как

user@host> ssh user2@host2 "echo $HOME"

распечатывает / home / user

Другой пример:

user@host> ssh user2@host2 "echo hello world | awk '{print \$1}'"

правильно распечатывает "привет".

person dogbane    schedule 20.11.2008
comment
Однако имейте в виду следующее: ssh user2@host 'bash -s' echo $HOME /home/user2 exit - person errant.info; 30.04.2013
comment
Просто добавим, что в for циклах, запущенных в ssh сеансе, переменную цикла нельзя экранировать. - person AlexeyDaryin; 22.04.2014
comment
Во многих ситуациях разумным способом исправить последний пример будет ssh user2@host2 'echo hello world' | awk '{ print $1 }', т.е. запустить сценарий Awk локально. Если удаленная команда производит огромное количество результатов, вы, конечно, не должны копировать все это обратно на локальный сервер. Между прочим, одинарные кавычки вокруг удаленной команды позволяют избежать необходимости экранирования. - person tripleee; 29.12.2015

Это расширение ответа YarekT для объединения встроенных удаленных команд с передачей переменных ENV с локального компьютера на удаленный хост, чтобы вы могли параметризовать свои скрипты на удаленной стороне:

ssh user@host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote host
  echo $ARG1 $ARG2
ENDSSH

Я нашел это исключительно полезным, потому что сохранил все в одном скрипте, чтобы он был очень удобочитаемым и поддерживаемым.

Почему это работает. ssh поддерживает следующий синтаксис:

ssh пользователь @ хост удаленная_команда

В bash мы можем указать переменные среды для определения перед запуском команды в одной строке, например:

ENV_VAR_1 = 'значение1' ENV_VAR_2 = 'значение2' bash -c 'echo $ ENV_VAR_1 $ ENV_VAR_2'

Это упрощает определение переменных перед запуском команды. В этом случае echo - это наша команда, которую мы выполняем. Все, что находится до echo, определяет переменные среды.

Итак, мы объединяем эти две функции и ответ YarekT, чтобы получить:

ssh user @ host ARG1 = $ ARG1 ARG2 = $ ARG2 'bash -s' ‹закрыть 'ENDSSH' ...

В этом случае мы устанавливаем для ARG1 и ARG2 локальные значения. Отправка всего после user @ host в качестве remote_command. Когда удаленная машина выполняет команду, ARG1 и ARG2 устанавливают локальные значения благодаря локальной оценке командной строки, которая определяет переменные среды на удаленном сервере, а затем выполняет команду bash -s, используя эти переменные. Вуаля.

person chubbsondubs    schedule 09.09.2011
comment
Обратите внимание, что если вы хотите передавать такие аргументы, как -a, вы можете использовать -. например 'ssh user @ host - -a foo bar' bash -s '‹script.sh'. И аргументы также могут идти после перенаправления, например. 'ssh user @ host' bash -s '‹script.sh - -a foo bar'. - person gaoithe; 10.03.2016
comment
Если какое-либо из значений env var содержит пробелы, используйте: ssh user@host "ARG1=\"$ARG1\" ARG2=\"$ARG2\"" 'bash -s' <<'ENDSSH'... - person TalkLittle; 24.09.2016
comment
Как я писал в другом комментарии, суть использования -s заключается в том, чтобы иметь возможность применять аргументы к сценариям, полученным через stdin. Я имею в виду, что вы также можете опустить его, если не собираетесь его использовать. Если вы его используете, нет причин использовать переменные среды: ssh user@host 'bash -s value1 value2' <<< 'echo "$@"' - person JoL; 18.09.2018

<hostA_shell_prompt>$ ssh user@hostB "ls -la"

Вам будет предложено ввести пароль, если только вы не скопировали открытый ключ пользователя hostA в файл authorized_keys в домашнем каталоге пользователя .ssh. Это позволит использовать аутентификацию без пароля (если она принята в качестве метода аутентификации в конфигурации ssh-сервера)

person Vinko Vrsalovic    schedule 20.11.2008
comment
Проголосовал за вас. Это верное решение. Очевидно, что ключи должны быть защищены, но они также могут быть аннулированы, как и пароль, через серверную часть. - person willasaywhat; 21.11.2008
comment
Я не думаю, что это ответ на вопрос. В примере показано, как выполнить удаленную команду, но не показано, как выполнить локальный сценарий на удаленном компьютере. - person Jason R. Coombs; 29.04.2010
comment
Не уверен, но вы не можете передать свой скрипт на hostA для запуска на hostB с помощью этого метода? - person nevets1219; 29.04.2010

Я начал использовать Fabric для более сложных операций. Fabric требует Python и несколько других зависимостей, но только на клиентской машине. Сервер должен быть только ssh-сервером. Я считаю, что этот инструмент намного более мощный, чем сценарии оболочки, переданные SSH, и стоит того, чтобы его настроить (особенно если вам нравится программировать на Python). Fabric обрабатывает выполнение сценариев на нескольких хостах (или хостах определенных ролей), помогает облегчить идемпотентные операции (например, добавление строки в сценарий конфигурации, но не в том случае, если она уже есть), и позволяет создавать более сложную логику (например, Python язык может предоставить).

person Jason R. Coombs    schedule 26.01.2011

Попробуйте запустить ssh user@remote sh ./script.unx.

person Jeremy    schedule 18.12.2009
comment
Это работает только в том случае, если сценарий находится в каталоге по умолчанию (домашнем) на удаленном компьютере. Думаю, вопрос в том, как запустить скрипт, хранящийся локально на пульте. - person metasim; 20.07.2010
comment
имя пользователя ssh @ ip chmod + x script.sh ‹br/› имя пользователя ssh @ ip путь к файлу sh на удаленном хосте - person mani deepak; 24.03.2014

Предполагая, что вы имеете в виду, что хотите сделать это автоматически с «локальной» машины, без ручного входа на «удаленную» машину, вам следует изучить расширение TCL, известное как Expect, оно предназначено именно для такого рода ситуаций. Я также предоставил ссылку на скрипт для входа / взаимодействия через SSH.

https://www.nist.gov/services-resources/software/expect

http://bash.cyberciti.biz/security/expect-ssh-login-script/

person Dexygen    schedule 20.11.2008

Я использую его для запуска сценария оболочки на удаленном компьютере (проверено на / bin / bash):

ssh deploy@host . /home/deploy/path/to/script.sh
person Is Ma    schedule 10.11.2018

ssh user@hostname ".~/.bashrc;/cd path-to-file/;.filename.sh"

настоятельно рекомендуется использовать исходный файл среды (.bashrc / .bashprofile / .profile). перед запуском чего-либо на удаленном хосте, потому что переменные среды целевого и исходного хостов могут быть отложены.

person Ankush Sahu    schedule 14.08.2019
comment
Это не объясняет, как переместить локальный сценарий на удаленный хост. - person kirelagin; 16.04.2020
comment
кажется, что перед ~ / .bashrc отсутствует пробел - person vhamon; 04.01.2021

если вы хотите выполнить команду, подобную этой команде temp=`ls -a` echo $temp в `` вызовет ошибки.

команда ниже решит эту проблему ssh user@host ''' temp=`ls -a` echo $temp '''

person Jinmiao Luo    schedule 21.09.2018

Ответ здесь (https://stackoverflow.com/a/2732991/4752883) отлично работает, если вы пытаетесь запустить сценарий на удаленной машине с Linux, используя plink или ssh. Это будет работать, если в сценарии есть несколько строк на linux.

** Однако, если вы пытаетесь запустить пакетный сценарий, расположенный на локальном linux/windows компьютере, а ваш удаленный компьютер - Windows, и он состоит из нескольких строк с использованием **

plink root@MachineB -m local_script.bat

не будет работать.

Будет выполнена только первая строка скрипта. Вероятно, это ограничение plink.

Решение 1:

Чтобы запустить многострочный пакетный скрипт (особенно если он относительно простой, состоящий из нескольких строк):

Если ваш исходный пакетный сценарий выглядит следующим образом

cd C:\Users\ipython_user\Desktop 
python filename.py

вы можете объединить строки вместе с помощью разделителя «&&» в вашем local_script.bat файле следующим образом: https://stackoverflow.com/a/8055390/4752883:

cd C:\Users\ipython_user\Desktop && python filename.py

После этого изменения вы можете запустить сценарий, как указано здесь @ JasonR.Coombs: https://stackoverflow.com/a/2732991/4752883 с:

`plink root@MachineB -m local_script.bat`

Решение 2:

Если ваш пакетный сценарий относительно сложен, может быть лучше использовать пакетный сценарий, который инкапсулирует команду plink, а также следующее, как указано здесь @Martin https://stackoverflow.com/a/32196999/4752883:

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe
person alpha_989    schedule 21.04.2018

Этот сценарий bash выполняет ssh на целевом удаленном компьютере и запускает некоторую команду на удаленном компьютере, не забудьте установить ожидание перед его запуском (на Mac brew install expect)

#!/usr/bin/expect
set username "enterusenamehere"
set password "enterpasswordhere"
set hosts "enteripaddressofhosthere"
spawn ssh  $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "somecommand on target remote machine here\n"
sleep 5
expect "$"
send -- "exit\n"
person Mohammed Rafeeq    schedule 30.05.2018
comment
это замечательно, если вы должны использовать пароли ... однако для пользы всех, кто смотрит дома, любая команда ssh должна использовать пару общедоступных + закрытых ключей, а не паролей ... однажды обновите свой ssh-сервер, чтобы полностью отключить пароли - person Scott Stensland; 01.03.2019

Вы можете использовать runoverssh:

sudo apt install runoverssh
runoverssh -s localscript.sh user host1 host2 host3...

-s удаленно запускает локальный сценарий


Полезные флаги:
-g использовать глобальный пароль для всех хостов (запрос единого пароля)
-n использовать SSH вместо sshpass, полезно для аутентификации с открытым ключом

person nowat    schedule 01.09.2019

Если сценарий короткий и предназначен для встраивания в ваш сценарий, и вы работаете под bash оболочкой, а также bash оболочка доступна на удаленной стороне, вы можете использовать declare для передачи локального контекста на удаленный. Определите переменные и функции, содержащие состояние, которое будет передано на удаленный компьютер. Определите функцию, которая будет выполняться на удаленной стороне. Затем внутри документа, читаемого bash -s, вы можете использовать declare -p для передачи значений переменных и использовать declare -f для передачи определений функций на удаленный компьютер.

Поскольку declare заботится о цитировании и будет анализироваться удаленным bash, переменные правильно заключены в кавычки и функции передаются должным образом. Вы можете просто написать сценарий локально, обычно я выполняю одну длинную функцию с работой, которую мне нужно выполнить на удаленной стороне. Контекст должен быть выбран вручную, но следующий метод достаточно хорош для любых коротких сценариев и безопасен - должен правильно обрабатывать все угловые случаи.

somevar="spaces or other special characters"
somevar2="!@#$%^"
another_func() {
    mkdir -p "$1"
}
work() {
    another_func "$somevar"
    touch "$somevar"/"$somevar2"
}
ssh user@server 'bash -s' <<EOT
$(declare -p somevar somevar2)    # transfer variables values
$(declare -f work another_func)   # transfer function definitions
work                              # call the function
EOT
person KamilCuk    schedule 07.02.2021

Если это один сценарий, все в порядке с указанным выше решением.

Я бы настроил Ansible для выполнения этой работы. Он работает таким же образом (Ansible использует ssh для выполнения сценариев на удаленной машине как для Unix, так и для Windows).

Он будет более структурированным и удобным в обслуживании.

person Abhishek    schedule 28.07.2020

Неясно, использует ли локальный сценарий локально установленные переменные, функции или псевдонимы.

Если это так, это должно сработать:

myscript.sh:

#!/bin/bash

myalias $myvar
myfunction $myvar

Он использует $myvar, myfunction и myalias. Предположим, они установлены локально, а не на удаленной машине.

Создайте функцию bash, содержащую скрипт:

eval "myfun() { `cat myscript.sh`; }"

Задайте переменную, функцию и псевдоним:

myvar=works
alias myalias='echo This alias'
myfunction() { echo This function "$@"; }

И экспортируйте myfun, myfunction, myvar и myalias в server, используя env_parallel из GNU Parallel:

env_parallel -S server -N0  --nonall myfun ::: dummy
person Ole Tange    schedule 24.01.2021

Сначала скопируйте скрипт на машину B с помощью scp

[пользователь @ machineA] $ scp / path / to / script user @ machineB: / home / user / path

Затем просто запустите скрипт

[пользователь @ machineA] $ ssh user @ machineB "/ home / user / path / script"

Это будет работать, если вы дали скрипту разрешение на выполнение.

person Community    schedule 20.11.2008
comment
привет, я применил рекомендованное предложение, но оно дало мне следующую ошибку [oracle @ node1 ~] $ ssh oracle @ node2: ./ home / oracle / au / fs / conn.sh ssh: node2: ./ home / oracle / au / fs / conn.sh: имя или служба неизвестны [oracle @ node1 ~] $ - person ; 20.11.2008
comment
'ssh oracle @ node2: ./ home / oracle / au / fs / conn.sh'? Неправильная командная строка, имя команды должно быть отделено от части user @ host пробелом, а не двоеточием. - person bortzmeyer; 15.12.2008
comment
Я голосую против этого, потому что это основное утверждение, что его нельзя запустить без копирования, неверно. - person Jason R. Coombs; 29.04.2010
comment
Было бы полезно, если бы Джейсон добавил, почему это неправильно, вместо того, чтобы просто констатировать факт. Бесполезный. - person Kris; 28.12.2013
comment
[пользователь @ machineA] $ ssh root @ MachineB 'bash -s' ‹/ machinea / путь / к / скрипту - person Oleksii Kyslytsyn; 30.06.2019
comment
и все же это лучше, чем большинство ответов - person sivann; 25.06.2020

person    schedule
comment
Интересно, что этот метод 'cat script.sh | ssh user @ host '- единственный, кто работает на меня, чтобы запустить сценарий оболочки на другом хосте. метод 'bash' ‹script.sh работает некорректно, но я не тратил время на устранение неполадок. Я даже скопировал скрипт на удаленный хост и вижу «файл не найден», хотя если я войду на хост и запустил скрипт, он работает. - person Jared Still; 06.08.2020