1

I want to run some commands each time when I log in to a remote system. Storing commands in .bashrc on remote is not an option.

What is the proper way to escape the escape chars inside of quotes in bash script for ssh? How can I write each command in new line?

My script

#!/bin/bash

remote_PS1=$'\[\033[01;32m\]\u@\[\033[03;80m\]\h\[\033[00m\]:\[\033[01;34m\]\!:\w\[\033[00m\]\$ '
ssh -t "$@" 'export SYSTEMD_PAGER="";' \
            'export $remote_PS1;' \
            'echo -e "set nocompatible" > /home/root/.vimrc;' \
            'bash -l;'

didn't work.

5
  • Use heredoc with ssh to avoid any escaping Commented Apr 4, 2021 at 6:07
  • 2
    You generally need two layers of quotes on commands to be sent over ssh: one to be parsed, applied, and removed by the local shell, and a second to be parsed, applied, and removed by the remote shell (see my answer here). Also, be aware what's happening locally vs remotely; in your current script, remote_PS1 is only defined in the local shell, not the remote one (and you shouldn't use $ when exporting it). Commented Apr 4, 2021 at 6:10
  • I defined remote_PS1 in local script but I tried to use it in third line. Commented Apr 4, 2021 at 6:20
  • Since the third line is in single-quotes, the local shell won't expand the $variable reference, just remove the single-quotes and pass the command on literally; the remote shell will then see it as an unquoted variable reference, try to expand it, get nothing, and therefore run the command export ;, which is invalid. Putting that line in double-quotes would cause a different problem; the local shell would expand the variable, and pass it to the remote shell as export <bunchofgibberishescapes> ; with no variable name. You have to think carefully about exactly what's happening where. Commented Apr 4, 2021 at 7:12
  • What you could use on the third line is "export PS1='$remote_PS1';" ` -- the double-quotes will allow $remote_PS1` to expand, but the single-quotes will protect that expanded value when it gets to the remote shell. Yes, this really is complicated (and if the value had any single-quotes in it, it'd be even more complicated). And as I suggested in the other answer, you can debug it by replacing ssh -t "$@" with echo, to see what'd be sent to the remote shell (i.e. the command after the local shell processes it, but before the remote shell does). Commented Apr 4, 2021 at 7:50

2 Answers 2

2

Escaping escape characters inside double-quotes and run them on remote server is way too complicated for me :) Instead, I wrote a remoterc file for remote and a small remotessh script. In remotessh, first I copy remoterc on remote machine and run bash command with that remoterc file interactively.

remoterc:

#!/bin/bash
SYSTEMD_PAGER=""
PS1="\[\033[01;32m\]\u@\[\033[03;80m\]\h\[\033[00m\]:\[\033[01;34m\]\!:\w\[\033[00m\]\$ "
echo -e "set nocompatible" > /home/root/.vimrc 

remotessh:

#!/bin/bash 
scp remoterc "$1":/home/root/ 
ssh "$1" -t "bash --rcfile remoterc -i"

It works :)

Sign up to request clarification or add additional context in comments.

Comments

2

You can use Bash's printf %q.

According to help printf:

%q      quote the argument in a way that can be reused as shell input

See the following example:

$ cat foo.sh
ps1='\[\033[1;31m\]\u:\w \[\033[0m\]\$ '
ps1_quoted=$( printf %q "$ps1" )
ssh -t foo@localhost \
    'export FOO=bar;' \
    "export PS1=$ps1_quoted;" \
    'bash --norc'

Result:

pic

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.