1

This is a kind of follow-up question to this question: ssh, start a specific shell, and run a command on the remote machine?, except more-specifically regarding ash, and focused on the fact that sourcing a .bashrc file as part of starting the shell in the ssh session doesn't work for me.

I'm on an embedded Linux device which has a busybox version of sh and ash, but there is no bash. We share a common username (root), and a common execution environment.

I'd like to have a few custom aliases and a custom PS1 Prompt String 1 variable, however.

Here is an example normal ssh session. Note that I'm using sshpass to pass my password to ssh, with my password stored in the ~/pw file.

You can see that the default shell is -sh and there are no aliases. The default PS1 prompt string also shows no path.

$ sshpass -f ~/pw ssh [email protected]
[root@device]$ echo $0
-sh
[root@device]$ alias
[root@device]$ 

The device has no bash, but it does have ash, which apparently is bash-like. So, I want to make that my shell as I ssh in. I also want to copy Ubuntu's default ~/.bashrc file, located in /etc/skel/.bashrc on the Ubuntu machine I'm ssh-ing from, to the device at /tmp/.bashrc so I can source it, and I want my ssh command to do that. I can't copy to ~/.bashrc on the remote device because the home dir is read-only.

I tried the following, but get the following error:

cmd:

sshpass -f ~/pw scp /etc/skel/.bashrc [email protected]:/tmp/.bashrc \
&& sshpass -f ~/pw ssh -t [email protected] '. /tmp/.bashrc'

result:

Connection to 192.168.0.2 closed.

No ssh session was established.

I then tried the following command, with the following result, showing that sourcing did not work, although the ash shell was entered.

$ sshpass -f ~/pw scp /etc/skel/.bashrc [email protected]:/tmp/.bashrc \
&& sshpass -f ~/pw ssh -t [email protected] '. /tmp/.bashrc; ash'
~ # echo $0
ash
~ # alias
~ # 

I can run . /tmp/.bashrc manually now though, and it works fine. Notice how after sourcing, which works, I have an improved prompt string and new aliases:

~ # . /tmp/.bashrc
ash: /tmp/.bashrc: line 16: shopt: not found
ash: /tmp/.bashrc: line 24: shopt: not found
ash: /tmp/.bashrc: line 111: shopt: not found
root@device:~# alias
l='ls -CF'
alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '"'"'s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'"'"')"'
la='ls -A'
ll='ls -alF'

You also see the ash errors from line 16, 24, and 111 due to shopt not being found. Even if I comment those out in the .bashrc file I send over, the results as shown above are still the same.

How can I get my above command to work? I'd like it to ssh in, set the shell to something more like bash, and source my /tmp/.bashrc file I scp'ed over.


On a similar embedded device which does have bash installed, this cmd works perfectly, as I document in my repo here:

sshpass -f ~/pw scp /etc/skel/.bashrc [email protected]:/tmp \
&& sshpass -f ~/pw ssh -t [email protected] 'bash --rcfile /tmp/.bashrc'

For bash, using bash --rcfile /tmp/.bashrc at the end of the ssh cmd is what I need. But, for the device withOUT bash, I need help getting this behavior with ash or similar.

2 Answers 2

2

Why are you running ash? A system with busybox is unlikely to have two different shells. (It's technically possible that /bin/sh is not the same shell as /bin/ash, but it would be a very unlikely setup on an embedded device.)

Apart from a few simple aliases or functions, very little of the typical content of .bashrc is likely to work in ash (or in any shell that isn't bash). Things that won't work include shopt, key bindings, prompt settings, any function that uses non-POSIX extension, any alias that refers to commands not present on the embedded device.

… ssh -t [email protected] '. /tmp/.bashrc; ash'

You're reading /tmp/.bashrc in the original shell, then running a different shell program. That different program doesn't inherit any of the shell's internal settings such as aliases. It's a completely different problem from ssh, start a specific shell, and run a command on the remote machine? which is about reading .profile, which sets environemnt variables, which are inherited.

BusyBox's ash reads commands from the file whose name is in $ENV when it starts interactively. (BusyBox's sh can be either ash or hush; since you have an ash command, yours is ash.) So you can set ENV to the name of the file where you want to read commands.

… ssh -t [email protected] 'export ENV=/tmp/.bashrc; sh -i'
7
  • 1
    Even when both /bin/sh and /bin/ash are symlinked to busybox, they probably behave differently. Busybox looks at argv[0] to find out what installable module and options for the module to use. So /bin/sh is likely "run Busybox ash shell with the more-POSIX flag"
    – Ben Voigt
    Commented Nov 11, 2021 at 23:03
  • Documentation for ash which mentions ENV variable: linux.die.net/man/1/ash Commented Nov 11, 2021 at 23:24
  • Setting ENV worked, as you said! Here is my final alias. I put this in ~/.bash_aliases on my Ubuntu machine and can now use gs_ssh to ssh into the device with the environment that I want. I customized the .bashrc file to my needs. Final alias and command: alias gs_ssh="sshpass -f ~/pw scp path/to/custom/.bashrc [email protected]:/tmp && sshpass -f ~/pw ssh -t -o 'ServerAliveInterval 60' [email protected] 'export ENV=/tmp/.bashrc; ash'". Note that using ash vs ash -i at the end seems to make no difference, perhaps because the shell is already interactive since we are using ssh -t? Commented Nov 11, 2021 at 23:31
  • Gilles, to answer your question: Why are you running ash? I suspect @BenVoigt is right in his comment above. When I run busybox --help to see a list of all functions inside it, I see ash and sh separately. My understanding is that ash is a lightweight substitute for bash, whereas sh is not. Commented Nov 11, 2021 at 23:43
  • @GabrielStaples Your understanding is wrong. BusyBox's comes with two different implementations of the sh language: one called ash, and one called hush. (And to add to the naming confusion, there are other implementations of sh also called ash.) Both can be considered a “lightweight substitute for bash”. Ash is a little more complete than hush but that comes with more code size, hence the two choices. On a given system, you only have one of them. sh is ash, it's available under both names, and I don't think BusyBox cares which name you use. Commented Nov 12, 2021 at 0:17
0

Your default shell is stored in the /etc/passwd file. Any user can change its default shell with the chsh command. The authorized shells are listed in /etc/shells. Of course, bash should be present before switching to this shell.

5
  • If I run: chsh, I get: -sh: chsh: not found. Commented Nov 11, 2021 at 22:56
  • I guess some embedded Linux system doesn’t contains all common commands. /etc/password could be edited by root with vi… but if the system is stripped down, it may lack bash too ! Start verifying the presence of bash ! Commented Nov 11, 2021 at 23:00
  • At the top of my question: "I'm on an embedded Linux device which has a busybox version of sh and ash, but there is no bash." If I run bash I get -sh: bash: not found. I'm pretty sure that's the whole point of ash: it is a light-weight substitute for bash. See: Ask Ubutu: What exactly is Busybox / Ash? Commented Nov 11, 2021 at 23:02
  • I see my PS1 Prompt String 1 defined in /etc/profile.d/prompt.sh it looks like, as export PS1="\[\033[1;34m\][\u@\h]$\[\033[0m\] ". Commented Nov 11, 2021 at 23:08
  • 1
    You can change it in your .profile. \w is a synonymous of your current directory. Then you can set PS1='\u@\h:\w\$' and get your current directory in your prompt… like with bash. Commented Nov 11, 2021 at 23:25

You must log in to answer this question.

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