As noted in comments to your question (terdon, bxm), the single quotes prevents your command from being expanded locally.
However, the remote environment is likely not populated because, quoting man 1 ssh
(bold text mine):
If a command is specified, it is executed on the remote host instead of a login shell.
A remote login shell can be explicitly invoked, though:
ssh myuser@remote-machine bash -lc \
"'"'mysql -u "$DB_USER" --password="$DB_PASS" "$DB_NAME" </tmp/dump.sql'"'"
Note the double layer of quoting: we make sure that the whole command is not expanded locally, by means of the inner single quotes, and that the remote host receives it enclosed in single quotes (the outer double-quoted ones), so that it doesn't undergo expansion and splitting before it is passed to Bash as the command string.
Alternatively, with no need for the extra quoting, you can have a remote login shell by serving your command to ssh
through standard input and invoking ssh
without a command argument:
echo 'mysql -u "$DB_USER" --password="$DB_PASS" "$DB_NAME" </tmp/dump.sql' |
ssh -T myuser@remote-machine
-T
is used to avoid the warning about a pseudo-terminal not being allocated when standard input is not a terminal.
Since your question is about Bash: a here string can also be used, adding a bit convenience:
ssh -T myuser@remote-machine <<<'mysql ...'
The actual kind of shell you need depends on how the remote environment is set up. When invoked as a non-interactive login shell, Bash sources several scripts: /etc/profile
(if it exists), then the first one that is found and readable among ~/.bash_profile
, ~/.bash_login
, and ~/.profile
; it likely won't source ~/.bashrc
. You may need to adjust your actual command based on the files that set the required environment variables.
. ~/.profile;
. You can debug the remote profile by sending it back to your local machine with echo commands, ordeclare -p "${@}" | cut -c -200
for the full story. – Paul_Pedant Jun 18 '20 at 16:22