SSH를 사용하여 원격 시스템에서 쉘 스크립트를 실행하는 방법은 무엇입니까?


1220

원격 컴퓨터에서 쉘 스크립트 (windows / Linux)를 실행해야합니다.

머신 A와 B 모두에 SSH가 구성되어 있습니다. 스크립트는 머신 A에 있으며 원격 머신 머신 B에서 일부 코드를 실행합니다.

로컬 및 원격 컴퓨터는 Windows 또는 Unix 기반 시스템 일 수 있습니다.

plink / ssh를 사용하여 실행할 수있는 방법이 있습니까?


6
같은 질문은 저기 serverfault에 이미 : serverfault.com/questions/215756/...은 그래서 아마이 질문을 마이그레이션 아무 소용이 없다.
sleske

9
서버 결함에 대한 질문에는 대답이 많지 않습니다. 아마도이 질문은 그 질문을 대체해야합니다.
Big McLargeHuge

5
이 답변을 개인적으로 좋아합니다 : unix.stackexchange.com/questions/87405/…
mikevoermans

27
또한 ssh는 소프트웨어 개발의 주요 도구이기 때문에 분명히 주제에 있어야합니다.
static_rtti

4
커피와 ssh 질문은 SO에 대해 동일한 정도의 주제를 공유하지 않습니다. 재개로 투표했습니다.
빈센트 캔틴

답변:


1192

기계 A가 Windows 상자 인 경우, -m 매개 변수와 함께 Plink ( PuTTY의 일부)를 사용할 수 있으며 원격 서버에서 로컬 스크립트를 실행합니다.

plink root@MachineB -m local_script.sh

머신 A가 유닉스 기반 시스템 인 경우 다음을 사용할 수 있습니다.

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

스크립트를 실행하기 위해 스크립트를 원격 서버에 복사 할 필요는 없습니다.


11
-s옵션 을 사용하면 이점이 있습니까? 이 매뉴얼 페이지-s 는 사용 여부에 관계없이 처리 옵션이 완료되면 표준 입력을 처리한다고 믿습니다 .
aeroNotAuto

78
필요한 스크립트의 경우을 sudo실행하십시오 ssh root@MachineB 'echo "rootpass" | sudo -Sv && bash -s' < local_script.sh.
bradley.ayers

6
@ bradley.ayers는 역사를 건너 뛰기 위해 'space'로 명령을 시작하는 것을 기억합니다 (PS를 HISTCONTROL=ignoreboth or ignorespace작동
시켜야 함

8
이미 루트로 로그인하고 있다면 어떤 상황에서 sudo가 필요합니까?
Brian Schlenker

21
@Agostino, 다음과 같은 매개 변수를 추가 할 수 있습니다 : ssh root@MachineB ARG1="arg1" ARG2="arg2" 'bash -s' < local_script.sh 크레딧은 아래 @chubbsondubs의 답변으로 완전히 이동하십시오.
Yves Van Broekhoven

633

이것은 오래된 질문이며 Jason의 대답은 잘 작동하지만 이것을 추가하고 싶습니다.

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 참조


4
# $ (sleep 5)
Olivier Dulac

50
종료 자 ( <<'ENDSSH') 주위에 작은 따옴표를 사용하면 문자열이 확장되지 않고 변수가 평가되지 않습니다. <<ENDSSH또는 <<"ENDSSH"확장을 원하는 경우 에도 사용할 수 있습니다 .
maackle

3
ExpectFTP와 같은 대화식 명령을 자동화해야 할 때 사용할 수 있습니다.
programaths

5
내가 Pseudo-terminal will not be allocated because stdin is not a terminal.메시지를 받았음을 주목하십시오 . -t -t그것을 피하기 위해 ssh를 params 와 함께 사용해야 합니다.
Buzut

8
<<- 'END'구문을 사용하려는 경우 heredoc 종료 구분 기호는 공백이 아닌 TAB을 사용하여 들여 쓰기해야합니다. stackexchange에서 복사 / 붙여 넣기하면 공간이 생깁니다. 탭으로 변경하면 들여 쓰기 기능이 작동합니다.
fbicknel 2016 년

249

또한 대상 호스트에서 변수를 선택하려면 이스케이프하는 것을 잊지 마십시오.

이것은 과거에 나를 잡아 냈습니다.

예를 들면 다음과 같습니다.

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}'"

"hello"를 올바르게 인쇄합니다.


2
그러나 다음 사항에 ssh user2@host 'bash -s' echo $HOME /home/user2 exit
유의하십시오

1
그냥에 있음을 추가 for로 실행 루프 ssh세션 루프 변수가 탈출하지 않아야합니다.
AlexeyDaryin

1
많은 상황에서 마지막 예제를 수정하는 깔끔한 방법 ssh user2@host2 'echo hello world' | awk '{ print $1 }'은 Awk 스크립트를 로컬에서 실행하는 것 입니다. 원격 명령이 엄청난 양의 출력을 생성하는 경우 로컬 서버로 다시 복사하지 않도록하려고합니다. 또한 원격 명령 주위의 작은 따옴표는 이스케이프 처리를 피합니다.
tripleee

151

이것은 인라인 원격 명령과 로컬 시스템에서 원격 호스트로 ENV 변수를 전달하여 원격 측에서 스크립트를 매개 변수화 할 수있는 YarekT의 답변을 확장 한 것입니다.

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

이 스크립트는 모두 하나의 스크립트로 작성하여 매우 읽기 쉽고 유지 관리가 가능하므로 매우 유용합니다.

왜 이것이 효과가 있습니까? ssh는 다음 구문을 지원합니다.

ssh user @ host remote_command

bash에서는 다음과 같이 한 줄에서 명령을 실행하기 전에 정의 할 환경 변수를 지정할 수 있습니다.

ENV_VAR_1 = 'value1'ENV_VAR_2 = 'value2'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 명령이 실행됩니다. 짜잔


1
-a와 같은 args를 전달하려면-를 사용할 수 있습니다. 예를 들어 'ssh user @ host--a foo bar'bash -s '<script.sh'입니다. 그리고 인수는 경로 재 지정 후 갈 수도 있습니다 (예 : 'ssh user @ host'bash -s '<script.sh--a foo bar').
gaoithe

8
env var 값에 공백이 포함 된 경우 다음을 사용하십시오.ssh user@host "ARG1=\"$ARG1\" ARG2=\"$ARG2\"" 'bash -s' <<'ENDSSH'...
TalkLittle

다른 의견에서 썼 듯이, 사용의 요점은 -sstdin을 통해 제공되는 스크립트에 인수를 적용 할 수 있다는 것입니다. 당신이 그것을 사용하지 않을 경우 당신은 그것을 생략 할 수 있습니다. 사용하면 환경 변수를 사용할 이유가 없습니다.ssh user@host 'bash -s value1 value2' <<< 'echo "$@"'
JoL

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

hostA 사용자의 공개 키를 user .ssh 디렉토리의 홈에있는 authorized_keys 파일에 복사하지 않은 경우 비밀번호를 묻는 메시지가 표시됩니다. 이를 통해 비밀번호없는 인증이 가능합니다 (ssh 서버 구성에서 인증 방법으로 승인 된 경우).


3
당신을 투표했습니다. 이것은 유효한 솔루션입니다. 분명히 키는 보호되어야하지만 서버 측을 통한 암호와 마찬가지로 무효화 될 수도 있습니다.
willasaywhat

8
나는 이것이 질문에 대답하지 않는다고 생각한다. 이 예는 원격 명령을 실행하는 방법을 보여 주지만 원격 시스템에서 로컬 스크립트를 실행하는 방법은 보여주지 않습니다.
Jason R. Coombs

확실하지 않지만이 방법을 사용하여 hostA에서 스크립트를 hostB에서 실행하도록 파이프 할 수 없습니까?
nevets1219

27

보다 정교한 작업을 위해 Fabric 을 사용하기 시작했습니다 . Fabric에는 Python과 몇 가지 다른 종속성이 필요하지만 클라이언트 시스템에만 필요합니다. 서버는 ssh 서버이면됩니다. 이 도구는 SSH로 전달한 쉘 스크립트보다 훨씬 강력하며 설정에 어려움이 있습니다 (특히 Python에서 프로그래밍을 즐기는 경우). Fabric은 여러 호스트 (또는 특정 역할의 호스트)에서 스크립트 실행을 처리하고, 구성 스크립트에 줄을 추가하는 등의 dem 등식 작업을 용이하게하는데 도움을줍니다. 언어는 제공 할 수 있습니다).


11

실행 해보십시오 ssh user@remote sh ./script.unx.


8
스크립트가 원격의 기본 (홈) 디렉토리에있는 경우에만 작동합니다. 질문은 원격에 로컬로 저장된 스크립트를 실행하는 방법입니다.
metasim

1
ssh username @ ip "chmod + x script.sh"<br/> ssh username @ ip "원격 호스트의 sh 파일 경로"
mani deepak



5

나는 이것을 사용하여 원격 컴퓨터에서 쉘 스크립트를 실행합니다 (/ bin / bash에서 테스트 됨).

ssh deploy@host . /home/deploy/path/to/script.sh

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

환경 파일 (.bashrc / .bashprofile / .profile)을 소싱하는 것이 좋습니다. 대상 및 소스 호스트 환경 변수가 달라질 수 있으므로 원격 호스트에서 무언가를 실행하기 전에.


로컬 스크립트를 원격 호스트로 이동하는 방법은 설명하지 않습니다.
kirelagin

2

temp=`ls -a` echo $temp `` 에서이 명령과 같은 명령을 실행하려면 오류가 발생합니다.

아래 명령은이 문제를 해결할 것입니다 ssh user@host ''' temp=`ls -a` echo $temp '''


1

여기에 대한 답은 ( https://stackoverflow.com/a/2732991/4752883 사용하여 원격 리눅스 컴퓨터에서 스크립트를 실행하려고하는 경우) 좋은 작품 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 :

배치 스크립트가 비교적 복잡한 경우 여기에서 @Martin https://stackoverflow.com/a/32196999/4752883 에서 지적한 것처럼 plink 명령을 캡슐화하는 배치 스크립트를 사용하는 것이 좋습니다 .

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

1

이 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"

1
당신이 완전히 암호를 차단하는 대신 업데이트에서 그러나 일단 ...없는 암호 개인 + 공개 키 쌍을 사용해야합니다 집에있는 ssh 명령을 보는 사람의 이익을 위해 ... 당신의 SSH 서버를 암호를 사용해야하는 경우이 중대하다
스콧 Stensland

-1

runoverssh 를 사용할 수 있습니다 :

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

-s 로컬 스크립트를 원격으로 실행


유용한 플래그 :
-g 모든 호스트에 글로벌 비밀번호 사용 (단일 비밀번호 프롬프트)
-n공개 키 인증에 유용한 sshpass 대신 SSH 사용


-24

먼저 scp를 사용하여 스크립트를 머신 B로 복사하십시오.

[user @ machineA] $ scp / path / to / script user @ machineB : / home / user / path

그런 다음 스크립트를 실행하십시오.

[user @ machineA] $ ssh user @ machineB "/ home / user / path / script"

스크립트에 실행 권한을 부여한 경우 작동합니다.


안녕하세요 추천 권장 사항을 적용했지만 다음 오류가 발생합니다. [oracle @ node1 ~] $ ssh oracle @ node2 : ./ home / oracle / au / fs / conn.sh ssh : node2 : ./ home / oracle / au / fs / conn.sh : 이름 또는 서비스를 알 수 없음 [oracle @ node1 ~] $

'ssh oracle @ node2 : ./ home / oracle / au / fs / conn.sh'? 잘못된 명령 행, 명령 이름은 콜론이 아닌 공백으로 user @ host 부분과 분리해야합니다.
bortzmeyer

5
복사하지 않고는 실행할 수 없다는 것이 기본 주장이기 때문에 이것을 다운 투표하고 있습니다.
Jason R. Coombs

Jason이 단순히 사실을 진술하는 대신 왜 틀린지 추가 한 것이 도움이되었을 것입니다. 도움이되지 않는.
Kris

[user @ machineA] $ ssh root @ MachineB 'bash -s'</ machinea / path / to / script
Oleksii Kyslytsyn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.