1

My Server machine run Window,and it installed Cygwin.

My Client machine run linux.

In Clinent machine.I do this:

[sikaiwei@login-1-2 v1.4]$ bash test.sh CHUN~19900405 [email protected]:/ifs2/BC_MG/GROUP/sikaiwei/ssh/v1.4
start
PuTTY Secure Copy client
Release 0.63
Usage: pscp [options] [user@]host:source target
   pscp [options] source [source...] [user@]host:target
   pscp [options] -ls [user@]host:filespec
Options:
 -V        print version information and exit
 -pgpfp    print PGP key fingerprints and exit
 -p        preserve file attributes
 -q        quiet, don't show statistics
 -r        copy directories recursively
 -v        show verbose messages
 -load sessname  Load settings from saved session
 -P port   connect to specified port
 -l user   connect with specified username
 -pw passw login with specified password
 -1 -2     force use of particular SSH protocol version
 -4 -6     force use of IPv4 or IPv6
 -C        enable compression
 -i key    private key file for authentication
 -noagent  disable use of Pageant
 -agent    enable use of Pageant
 -batch    disable all interactive prompts
 -unsafe   allow server-side wildcards (DANGEROUS)
 -sftp     force use of SFTP protocol
 -scp      force use of SCP protocol
end

It seems warn me that I use 'pscp' in my test.sh file worngly! But I don't. And my test.sh is:

#!/bin/bash
sshpass -p 'CHUN~19900405' ssh [email protected] '
echo start;
touch final_result.txt;
pscp -pw $1  final_result.txt $2;
echo end;
';

But when I use ".." instead of '..',like

#!/bin/bash
sshpass -p 'CHUN~19900405' ssh [email protected] "
echo start;
touch final_result.txt;
pscp -pw $1  final_result.txt $2;
echo end;
";

It don't repost error :

[sikaiwei@login-1-2 v1.4]$ bash test.sh CHUN~19900405 [email protected]:/ifs2/BC_MG/GROUP/sikaiwei/ssh/v1.4
start
end

I must use '..' instead of ".." to use enviorment variable of Server machine.like

[sikaiwei@login-1-2 v1.4]$ sshpass -p 'CHUN~19900405' ssh 172.16.22.53 -l sikaiwei   "getId=$ORANGE;echo $ORANGE;ORANGE=$((ORANGE+1));echo $ORANGE;echo 'getId is '+$getId;"

The $ORANGE is variable of Server machine.

So I must use '..',and how to still use $1,$2 to get arguements ?

John Militer
  • 773
  • 4
  • 14
  • 29
orange
  • 75
  • 1
  • 1
  • 8

3 Answers3

2

Variables are not expanded in single quotes, which is how you are passing the commands in the first instance. As such, in the first case, the shell on the remote end never receives your values, it just receives literal $1 and $2, and they do not exist, so they expand to nothing.

$ var=foo
$ echo '$var'
$var
$ echo "$var"
foo

pscp therefore gets no values when you pass $1 and $2 (because they do not exist on the remote shell), so it errors out at startup. This is how pscp ends up getting invoked:

pscp -pw final_result.txt

Use double quotes when you want variables to be expanded by the current shell, not single quotes. Using single quotes in this case would only be appropriate if you wanted the variables to expanded by the remote shell.

Chris Down
  • 122,090
  • 24
  • 265
  • 262
  • oh!I know.But if I must use '..' instead of ".." to get enviorment variable of Server machine,what should I do?Transfer the $1 ,$2 to Server machine? – orange Dec 20 '13 at 09:27
  • You'd need to invoke a shell on the remote machine, passing the arguments along. Note that when doing this, the first argument is `$0`, not `$1`. – Chris Down Dec 20 '13 at 09:32
  • I reedit question.I have to leave for hours..Sorry.. – orange Dec 20 '13 at 09:34
  • 1
    @orange you **don't have** to use single quotes (unless you have no way to type the double quotes, of course). And even if you want to, you can mix them freely: `'echo Hello "'"$1"'"!'` will - in case of the first argument (`$1`) being `"world population"` - print: `Hello world population!`. Thus you can use the advantages of both types of quoting. – peterph Dec 20 '13 at 11:59
  • `'echo Hello "'"$1"'"!'` works well! But why can't use `'echo hello "$1"'` although it don't work?I don't know why... – orange Dec 21 '13 at 03:13
  • @orange Because that includes *literal* quotes, not quoting characters for the shell to interpret. Compare `echo 'foo "bar" baz'` and `echo 'foo '"bar"' baz'`. – Chris Down Dec 21 '13 at 05:18
1

In the case of double quotes, the shell peeks inside the quotes to look for three things: variables indicated by $ character, commands to be run indicated by backwards quotes, and escaping the characters using \. Other than those three things, there is no difference between single and double quotes. Check the following commands:

$ foo=42
$ echo "$foo"
42
$ echo '$foo'
$foo
$ echo '\$foo'
\$foo
$ echo "\$foo"
$foo
unxnut
  • 5,908
  • 2
  • 19
  • 27
  • 1
    Note that command substitution is not exclusively accessible via the mentioned `\`` -- POSIX defines `$(`, which is superior for quite a few reasons (the main one being that nesting is much more legible). – Chris Down Dec 21 '13 at 06:05
1

You can use single quotes for your remote ssh command and still use $1 and $2 in your test.sh script to access locally defined values by combining ssh and bash -c 'cmd1; cmd2' _ arg1 arg2 [...].

# example of how to combine "ssh" and "bash -c" to get variables expanded by the
# current shell and thus make local values accessible by remote ssh command 
(
set -xv
echo ssh localhost 'bash -c '\''printf "%s\n" "$1" "$2" "$3"  "$4"  "$5" "$PWD" | cat -n'\''' _ arg1 arg2 "$HOME" "$PWD" arg5
ssh localhost 'bash -c '\''printf "%s\n" "$1" "$2" "$3"  "$4"  "$5" "$PWD" | cat -n'\''' _ arg1 arg2 "$HOME" "$PWD" arg5
)


# test.sh
#!/bin/bash
sshpass -p 'CHUN~19900405' ssh [email protected] 'bash -c '\''
echo start;
touch final_result.txt;
pscp -pw "$1"  final_result.txt "$2";
echo end;
'\''' _ "$1" "$2";
catto
  • 11
  • 1