Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shell function issue - remove the single quote from shell statement

Tags:

shell

sh

I am getting a issue running below command:

when I run: cmssh 12np, I meant to invoke the defined function cmssh, eventually I am expecting a shell command line like this:

sshpass -p password ssh mydomain\\[email protected]

, see below source:

alias 12np='ssh mydomain\\stephencheng@[email protected]'


function cmssh () {
   set -x
   local aliascmd=$1
   cmdstr=$(alias $aliascmd | cut -d'=' -f2 | cut -d"'" -f2)
   echo $cmdstr
   sshpass -p "$cmpw" $cmdstr
   #debug cmdstr : sshpass -p password 'ssh mydomain\\[email protected]'
}

however, the final step always render the result as:

sshpass -p password 'ssh mydomain\\[email protected]'

I have attempted many ways to try to remove the single quote, but got no idea how it is possible.

See the debug info:

~  cmssh 12np
+cmssh:2> local 'aliascmd=12np'
+cmssh:4> cmdstr=+cmssh:4> alias 12np
+cmssh:4> cmdstr=+cmssh:4> cmdstr=+cmssh:4> cut '-d=' -f2
+cmssh:4> cut '-d'\' -f2
+cmssh:4> cmdstr='ssh mydomain\\[email protected]'
+cmssh:7> echo 'ssh mydomain\\[email protected]'
ssh mydomain\\[email protected]
+cmssh:8> sshpass -p password 'ssh mydomain\\[email protected]'
sshpass: Failed to run command: No such file or directory

Thanks

like image 578
stephen cheng Avatar asked Nov 10 '22 09:11

stephen cheng


1 Answers

Note: At this point it is not clear what specific shell the OP uses. This answer makes a general point and then discusses bash and zsh.

Your immediate problem is unrelated to quoting: The error message suggests that the executable sshpass is not in your $PATH.

Your string ($cmdstr) doesn't actually contain single quotes - they are an artifact of running bash or zsh with set -x in effect.

However, there are additional issues:


The way you parse the alias definition in cmssh() turns the \\ in your alias definition from a (conceptually) quoted single \ into literal string \\ (two literal \ chars.)

A simple fix in this case is to add another layer of evaluation by having xargs (without arguments) echo the string:

cmdstr=$(alias $aliascmd | cut -d"'" -f2 | xargs)

Note that I've eliminated the =-based cut command, which is not needed.

In general, though, parsing alias definitions this way is fragile.

At that point I would expect your code to work in bash, though not yet in zsh (see below). Note that simply removing function  from the beginning of your function definition would make your code work in sh (a POSIX-features-only shell), too.


The final problem affects only zsh, not bash:

zsh by default doesn't perform word splitting on $cmdstr in the sshpass -p "$cmpw" $cmdstr command, so that 'ssh mydomain\[email protected]' is passed as a SINGLE argument to sshpass.

To turn on word splitting when evaluating $cmdstr and thus pass its tokens as separate arguments, refer to it as ${=cmdstr}:

sshpass -p "$cmpw" ${=cmdstr}

Note that this feature is zsh-specific.

like image 173
mklement0 Avatar answered Dec 06 '22 19:12

mklement0