如何使用参数在 ssh 上执行远程命令?

在我的 .bashrc中,我定义了一个函数,以后可以在命令行中使用:

function mycommand() {
ssh user@123.456.789.0 cd testdir;./test.sh "$1"
}

使用此命令时,只在远程主机上执行 cd命令; 在本地主机上执行 test.sh命令。这是因为分号分隔了两个不同的命令: ssh命令和 test.sh命令。

我尝试定义函数如下(注意单引号) :

function mycommand() {
ssh user@123.456.789.0 'cd testdir;./test.sh "$1"'
}

我尝试将 cd命令和 test.sh命令保持在一起,但是没有解析 $1参数,这与我给函数的内容无关。它总是尝试执行命令

./test.sh $1

在远程主机上。

如何正确定义 mycommand,以便在更改到目录 testdir之后在远程主机上执行脚本 test.sh,并且能够将给予 mycommand的参数传递给 test.sh

233872 次浏览

Do it this way instead:

function mycommand {
ssh user@123.456.789.0 "cd testdir;./test.sh \"$1\""
}

You still have to pass the whole command as a single string, yet in that single string you need to have $1 expanded before it is sent to ssh so you need to use "" for it.

Update

Another proper way to do this actually is to use printf %q to properly quote the argument. This would make the argument safe to parse even if it has spaces, single quotes, double quotes, or any other character that may have a special meaning to the shell:

function mycommand {
printf -v __ %q "$1"
ssh user@123.456.789.0 "cd testdir;./test.sh $__"
}
  • When declaring a function with function, () is not necessary.
  • Don't comment back about it just because you're a POSIXist.

Starting Bash version 4.4, it can also be simplified to this:

function mycommand {
ssh user@123.456.789.0 "cd testdir;./test.sh ${1@Q}"
}

See ${parameter@operator} section in Shell Parameter Expansion.

Reviving an old thread, but this pretty clean approach was not listed.

function mycommand() {
ssh user@123.456.789.0 <<+
cd testdir;./test.sh "$1"
+
}

This is an example that works on the AWS Cloud. The scenario is that some machine that booted from autoscaling needs to perform some action on another server, passing the newly spawned instance DNS via SSH

# Get the public DNS of the current machine (AWS specific)
MY_DNS=`curl -s http://169.254.169.254/latest/meta-data/public-hostname`




ssh \
-o StrictHostKeyChecking=no \
-i ~/.ssh/id_rsa \
user@remotehost.example.com \
<< EOF
cd ~/
echo "Hey I was just SSHed by ${MY_DNS}"
run_other_commands
# Newline is important before final EOF!


EOF

I'm using the following to execute commands on the remote from my local computer:

ssh -i ~/.ssh/$GIT_PRIVKEY user@$IP "bash -s" < localpath/script.sh $arg1 $arg2

A little trick for me, using the "bash -s" they said they allow POSITIONAL ARGS but apparently the $0 is already reserved for whatever reason... Then using twice the same args rocks like so:

ssh user@host "bash -s" < ./start_app.sh -e test -e test -f docker-compose.services.yml

Solution: you want to be able connect to machine remotely using ssh protocol and trigger/run some actions outside.

on ssh use a -t flag, from documentation:

-t Force pseudo-terminal allocation.
This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.

formula:

ssh -i <key-path> <user>@<remote-machine> -t '<action>'

Example: as administrator I want to be able to connect remotely into ec2 machines and trigger a revert process for a bad deployment on a several machines in a raw, moreover you better implement this action as an automation script that use ips as an arguments and running on different machines in parallel.

ssh -i /home/admin/.ssh/key admin@10.20.30.40 -t 'cd /home/application && make revert'