3

I have a server with an alias as follows:

~/.bash_aliases 
alias update='sudo apt update && sudo apt -y upgrade'

Now I want to create a shortcut from my desktop that can simply trigger this script remotely over sshpass: For a simple login, it works as follows:

sshpass -p "<password>" ssh <user>@<host>

But adding the alias as ssh command does not work and simply closes the terminal without action:

sshpass -p "<password>" ssh <user>@<host> 'update'

Question: is it possible at all?

membersound
  • 1,410
  • 1
    ... ssh -t user@localhost /bin/bash -ic 'update' –  Jan 14 '21 at 09:21
  • @bac0n would you consider making this an answer (i.e. that alias expansion only occurs by default in an interactive shell, and sudo requires a tty)? – steeldriver Jan 14 '21 at 14:39

2 Answers2

1

In my first example, I made it easy by turning the bash session into an interactive shell, which sets the expand_aliases shopt_option. There is also a case-statement at the beginning of .bashrc that disallows sourcing .bashrc in non-interactive shells, which in turn, means your .bash_aliases won't be sourced. Furthermore, even if ssh will interpret this as a non-interactive session, you may use the -t option to force a pseudo-terminal allocation for menus and screen-based applications to work.

ssh -t user@localhost '/bin/bash -ic update'

It can be accomplished in non-interactive shells, as well, but apt will still need a pseudo-terminal, though (can be solved by changing the frontend used by apt to a non-interactive choice).

ssh -t user@localhost '/bin/bash --init-file ~/.bash_aliases -O expand_aliases -c update'

Next is the use of -p passwords in sshpass that does not seem to die off. sshpass should never be used in this way, ever. I can't see a scenario where this is needed. First, it will end up in your history, i.e., of course, you don't have it turned off. It may also, in some circumstances, end up in the ps tree. sshpass makes very little to hide the pass in this mode. You should at least use the file option or SSHPASS=.

editor .ssh/passwd_credentials && chmod 400 $_

passwd_credentials should only contain the password.

And is used by the -f option.

sshpass -f ~/.ssh/passwd_credentials ssh user@localhost

You may also encapsulate your ssh command in a script file.

#!/bin/sh
SSHPASS='password' sshpass -e ssh user@localhost
0

Using sshpass will not trigger the server to load the aliases, but you can pass the commands like this:

sshpass -p <password> ssh <user>@<host> sudo /usr/bin/apt update && sudo /usr/bin/apt -y upgrade

HOWEVER ... you're going to get a message like this:

sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper

Which means you'll need to do a very ugly thing to make the system do what you want:

sshpass -p <password> ssh <user>@<host> echo <password> | sudo /usr/bin/apt update && echo <password> | sudo /usr/bin/apt -y upgrade

This method is suboptimal for a number of reasons, but it will technically accomplish your goals. Depending on what you're trying to accomplish, it may make sense to look at using unattended-upgrades instead.

  • Thanks for the hint. Would you favor unattended-upgrades over apt-cron? – membersound Jan 17 '21 at 11:03
  • If you don't plan on being "present" for the upgrade, then yes. Unattended upgrades will handle security and other critical updates automagically. Blindly firing a cron task off to servers will update all software, which can have consequences if you're not paying attention. –  Jan 17 '21 at 11:42