When I turned on vi mode in bash by setting set -o vi suddenly the tab completion was broken, and a literal tab was inserted. How can this be fixed?
- 333
- 1
- 8
1 Answers
TL;DR Solve by creating ~/.profile with
if [ $0 != -bash ]; then
exec -l bash
fi
Long version:
After searching for quite a while I found that on DSM6 bash runs in posix mode (verify with set -o) and tab completion does not work in vi mode in posix mode (bash completion in Posix mode). I tried the proposed solution by adding bind TAB:complete to my ~/.bashrc but that didn't work. I also tried to turn off posix mode with set +o posix and this worked, but only on the commandline and not when set in ~/.bashrc.
So I tried figuring out why bash would start in posix mode by default. I discovered that my login shell was set to /bin/sh (you can find this in /etc/passwd) which is symlinked to /bin/bash (verify with ls -l /bin/sh).
In the bash man pages it says that
If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.
so the solution it seems, was changing the login shell to /bin/bash. After I did this I couldn't ssh to my synology anymore, reason: Permission denied, please try again.
The cause? Apparently, Synology disallows any other login shells than ash or sh and they patched and compiled this into the OpenSSH binary (why the &*#$% do they think this is a smart idea?!)
So what to do? The proposed solution is to start a new bash session by creating ~/.profile with
if [ $0 != -bash ]; then
exec -l bash
fi
and now setting set -o vi in ~/.bashrc works as expected. Only problem is that the default profile in /etc/profile is not read anymore, so you have to set a nice prompt (PS1) yourself in ~/.bashrc. You can copy a standard ubuntu ~/.bashrc or you can have a look at the standard PS1 in /etc.defaults/.bash_profile.
- 333
- 1
- 8
-
By running `exec /bin/bash`, you get a "child" shell instead of a login shell. You need to add the `-l` switch to `exec` in order to get a login shell. Also be warned that by doing so your current test will get in an infinite loop. :) Try something like this instead : `if [ $0 = -bash ]; then exec -l bash; fi` – Nicolas Melay Feb 07 '23 at 12:49
-
of course this should be `[ $0 != -bash ]` instead of `[ $0 = -bash ]` ! – Nicolas Melay Feb 07 '23 at 13:56
-
@NicolasMelay Thanks, I hadn't realized that, I changed it to your suggestion! – Gerhard Burger Feb 09 '23 at 08:57