SSH + Sudo + Expect in Bash script: Run command with sudo in remote machine

9,426

Solution 1

I think you missed a level of quotes escaping. At this high level of escaping, it is best to simply make a little script for every stage where otherwise quotes would be required.

Otherwise, you could try this modified version (but mind you, I don't encourage this coding style!)

function _remoteInstallation(){
    local retval=1
    local debToInstall=$(basename "$1")
    local remoteMachine="$2"
    spawned=$(expect -d -c "
          set timeout 1800
          spawn \"/usr/bin/ssh -t borrajax@$remoteMachine /usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall\"
          expect {
                \"Are you sure you want to continue connecting\" { send \"yes\r\"; exp_continue }
                \"password\" { send \"myPassword\r\";  exp_continue }
                \"[sudo] password\" { send \"myPassword\r\";  exp_continue }
                default { exit 1 }
          }
    " )
    retval=$?
    return $retval
}

Solution 2

Why do people always use this ugly expect stuff with ssh? Use ssh keys and you are done (read up on public key cryptography for theory, just use ssh-copy-id remotemachine once and for all for practice). Then usage is as simple as

ssh remote-machine "remote-shell-command" > local-redirection-of-command-output

As soon as you don't have to juggle between 3 levels of quoting, you will naturally write correct commands.

Share:
9,426

Related videos on Youtube

BorrajaX
Author by

BorrajaX

Updated on September 18, 2022

Comments

  • BorrajaX
    BorrajaX over 1 year

    I am trying to automate the deploy of some .deb packages with an script. I want to execute sudo dpkg -i $myDeb.deb in a list of remote machines I can access with ssh.

    I've tried to automate the command with 'expect' inside a bash script, but I am obviously doing something wrong because I get a number of different errors (depending on where I put the quotation marks, basically)

    This is the function I have (will be called with something like: _remoteInstallation "myPackage115.deb" "192.168.1.55". I know that in the remote machine, the .deb is going to be located in $HOME/Documents/:

    function _remoteInstallation(){
        local retval=1
        local debToInstall=$(basename "$1")
        local remoteMachine="$2"
        spawned=$(expect -d -c "
              set timeout 1800
              spawn "/usr/bin/ssh -t borrajax@$remoteMachine /usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall"'
              expect {
                    \"Are you sure you want to continue connecting\" { send \"yes\r\"; exp_continue }
                    \"password\" { send \"myPassword\r\";  exp_continue }
                    \"[sudo] password\" { send \"myPassword\r\";  exp_continue }
                    default { exit 1 }
              }
        " )
        retval=$?
        return $retval
    }
    

    With the quotes in the spawned area like that, I get

    expect: invalid option -- 't'
    

    If I change it to:

     spawn /usr/bin/ssh -t borrajax@$remoteMachine '/usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall'
    

    It looks like is trying to run the sudo dpkg command locally (first ssh(s) to '$remoteMachine' and then runs sudo dpkg locally, like two separate commands)

    With this:

    spawn '/usr/bin/ssh -t borrajax@$remoteMachine \'/usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall\''
    

    I get that couldn't execute "'/usr/bin/ssh": no such file or directory (which is not true)

    ... and at this point, I ran out of ideas... :-)

    Any hint will be appreciated. Thank you.

  • BorrajaX
    BorrajaX almost 12 years
    I'm afraid that's not an option in this case. I can't set my keys in the remote machines.
  • BorrajaX
    BorrajaX almost 12 years
    Almost... It turns out that the brackets in the \"[sudo]\" option were messing it up. I finally got it working with the spawn area looking like: spawn /usr/bin/ssh -t zignage@$remoteMachine \"/usr/bin/sudo /usr/bin/dpkg -i /home/zignage/Documents/$debToInstall\" and scaping the braces in sudo (\"\[sudo\]\")