0

This uses "process substitution" (<()) and a "heredoc" (cat << EOF...EOF) to open a new bash process where it runs the startup "file" (--rcfile) containing alias foo="echo hey you. Here is the command:

bash --rcfile <(
cat << EOF
alias foo="echo hey you"
EOF
)

It works on Ubuntu just fine, as you can see here:

$ bash --rcfile <(
> cat << EOF
> alias foo="echo hey you"
> EOF
> )
$ foo
hey you
$ alias
alias foo='echo hey you'

However, when I try to run this on certain embedded Linux devices, I get the following error. Why? How do I make it run there too?

-sh: syntax error: unexpected "("

Full output:

$ bash --rcfile <(
-sh: syntax error: unexpected "("
$ cat << EOF
> alias foo="echo hey you"
> EOF
alias foo="echo hey you"
$ )
-sh: syntax error: unexpected ")"

In case this helps, here are my which bash and bash --version outputs on Ubuntu vs the embedded Linux device:

# 1. Ubuntu

$ which bash /bin/bash $ bash --version GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

2. Embedded Linux device

$ which bash /bin/bash $ bash --version GNU bash, version 5.0.16(1)-release (aarch64-buildroot-linux-gnu) Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

Not a duplicate:

This is related but does not seem to be a duplicate: dash reports 'Syntax error: "(" unexpected' when using process substitution.

Related:

  1. [my own question] https://stackoverflow.com/questions/69891328/what-is-the-syntax-in-shell-bash-and-how-do-i-search-for-it

Notes to self

My end-goal is to automatically create some custom aliases when I ssh in, like this perhaps:

ssh -t username@ip_address '/bin/bash --rcfile <(
cat << EOF
alias foo="echo hey you"
EOF
)'

Update: done! Here is what I came up with:

# Store your password into a file
echo "my_password" > ~/pw

Manually add something like this to your ~/.bash_aliases (recommended) or ~/.bashrc file on the PC

you are ssh-ing FROM:

alias gs_ssh="sshpass -f ~/pw scp /etc/skel/.bashrc root@192.168.0.2:/tmp
&& sshpass -f ~/pw ssh -t -o 'ServerAliveInterval 60' root@192.168.0.2 'bash --rcfile /tmp/.bashrc'"

See my repo here: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/tree/master/home/.ssh#optional-but-recommended-alias.

  • You have a device with bash, sure, but are you running this command in bash? – muru Nov 09 '21 at 00:42
  • @muru, I'm typing bash --rcfile..., so it is running it in bash right there, no? The --rcfile part and everything thereafter are the parameters to the bash cmd. – Gabriel Staples Nov 09 '21 at 00:45
  • 2
    Depends on what shell you're typing bash --rcfile into. That's the one that interprets the <(...) – muru Nov 09 '21 at 00:47
  • @muru: aaaah; that makes sense! That's running in sh I think. So, first I must run bash and THEN I can run that next cmd with the process substitution. – Gabriel Staples Nov 09 '21 at 00:48
  • @muru, okay: manually running bash first allows me to then run the cmd fine on the Linux device. BUT, I cannot seem to script the two cmds together as the first shell is what always interprets both of them. So, I'm still stuck. – Gabriel Staples Nov 09 '21 at 00:52
  • Note: running echo $0 on the embedded Linux device shows -sh, meaning it is running sh by default when I first log in. – Gabriel Staples Nov 09 '21 at 00:54

2 Answers2

2

Do the embedded Linux devices support /dev/fd/ entries? If they do, try passing the initialization commands over file descriptor #3, like this:

bash --rcfile /dev/fd/3 3<<EOF
alias foo="echo hey you"
exec 3<&-
EOF

EDIT: Stéphane Chazelas suggested adding exec 3<&- as the final command in the "script"; this closes the file descriptor, so it's not left dangling for the entire shell session.

2

Whether or not the syntax of your command is supported or not is determined by whatever shell you are currently running.

Your current shell is sh when you try to execute your bash --rcfile <(...) command, which is evident from the error message where the shell identifies itself as a sh shell running as a login shell. This shell does not generally understand process substitutions.

One way to work around this is to first exec bash, which is replacing the current shell with a shell that understands process substitutions, or to do as is suggested by Gordon Davisson and provide the temporary initialization file via an alternative file descriptor.

exec bash

bash --rcfile <( cat <<'BASHRC' alias foo='echo bumblebee' BASHRC )

bash --rcfile /dev/fd/3 3<<'BASHRC'
alias foo='echo bumblebee'
exec 3<&-
BASHRC

Note that you, in either case, most likely want to quote the here-document, unless you need the current shell to carry out expansions in the document before the new bash shell reads it. You may also want to use exec bash if replacing the current shell completely is what you want to do.

Kusalananda
  • 333,661
  • Ideally, the first example would work as a single command, but it does not. Rather, exec bash (or just bash) must be run first, and then after running that I can copy/paste the next part of the command and it works with process substitution. It looks like I cannot script the whole thing as a single command while having the bash part run first. – Gabriel Staples Nov 09 '21 at 16:36
  • How is exec bash different from bash anyway? Both seem to work the same in testing. – Gabriel Staples Nov 09 '21 at 16:37
  • 1
    @GabrielStaples If you give the command bash, you start a bash shell session. If you then say exit in that session, you get back to the initial shell. With exec bash, you replace the current shell with a bash shell session, which means that if you type exit, you terminate that terminal session completely (or log out, if were logged in via a text console or SSH). – Kusalananda Nov 09 '21 at 17:16
  • Ahhh, I actually noticed that when I typed exit a few minutes ago but didn't understand the new and "aberrant" behavior, nor why it happened! – Gabriel Staples Nov 09 '21 at 17:19