1

I want to read logs conveniently from my server. I'm trying to write a script that reads output of journalctl from my server, applying the parameters I pass to the script to journalctl call. I may want to apply various filters, so I want arguments to my script to translate to journalctl's arguments. For example

bin/log --since '2 days ago'

would run

ssh host journalctl --since '2 days ago'

I tried this:

#/usr/bin/env bash
ssh host journalctl "$@"

But when I call

bin/log --since '2 days ago'

I just says:

Failed to parse timestamp: 2

Ok, we got an argument with spaces that seems to transform to multiple arguments when passed as part of a command over SSH. Then I tried something like this:

#/usr/bin/env bash
ssh host bash -c 'journalctl autotests "$@"'

You can guess that doesn't do what I need.

How the hell do I pass $@ over ssh?

1 Answer 1

2

This question: How to execute complex command line over ssh is somewhat related. My answer there concentrates on the case where nothing is expanded locally; you want to expand $@ locally, it makes things more complicated. Still the linked resource may give you some insight into how these things work.

In your case the easiest way is to use the Q operator (see the beginning of this another answer of mine):

#!/usr/bin/env bash
ssh host "journalctl autotests ${@@Q}"

The above code won't work in pure sh, you need (local) bash. The "shebang" in your question is #/usr/bin/env bash, it's not a shebang, it's just a comment; a shebang should start with #!. The above code uses a proper shebang.

Note if you do:

ssh host bash -c "journalctl autotests ${@@Q}"

then the shell code on the remote side will lack one level of quotes. If you really need bash -c then this is what you can do:

#!/usr/bin/env bash
cmd="journalctl autotests ${@@Q}"
ssh host "bash -c ${cmd@Q}"

The additional usage of @Q gives you the additional level of quoting (or escaping) you need. But in this exact case you most likely don't need bash -c at all, the first command I gave you should work.

3
  • One caveat about this: the @Q modifier adds bash-compatible quoting/escaping. In some (rather obscure) situations, if the remote shell is something other than bash, it might not parse the quoting/escaping as expected, leading to weird problems. Commented Sep 19, 2023 at 1:54
  • @GordonDavisson I think there is nothing obscure in different shells handling input commands differently, but yeah, there can be a shell on the other end other than bash. I wonder how this whole situation can be handled in fish, for instance.
    – jojman
    Commented Sep 19, 2023 at 15:17
  • @jojman I think that it'll work with fish as the remote shell, unless the variable contains control characters (which will make @Q use ANSI-C quoting mode, which I think only bash, zsh, and ksh support), or \\ or \' or ends with \ (which cause trouble because fish interprets \\ and \' inside single-quoted strings). Commented Sep 19, 2023 at 17:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .