Skip to content

Shells

ShellPathNotes
bash/bin/bashDefault on most distros. Feature-rich, widely scripted against.
sh/bin/shPOSIX shell. Often a symlink to dash (Debian/Ubuntu) or bash. Minimal features.
zsh/bin/zshDefault on macOS. Superset of bash with better completion, theming, plugins.
dash/bin/dashLightweight POSIX shell. Fast but no interactive features.
fish/usr/bin/fishUser-friendly, auto-suggestions, not POSIX-compatible.
tmux/screenTerminal multiplexers (not shells, but wrap shells).
ShellNotes
cmd.exeLegacy Windows command prompt. Limited scripting.
PowerShell.ps1 scripts. Object-oriented pipeline. Default on modern Windows.
PowerShell Core (pwsh)Cross-platform PowerShell (Linux/macOS/Windows).

Terminal window
# Linux — several methods
echo $SHELL # Default login shell (not necessarily current)
echo $0 # Current shell process name
ps -p $$ # Process info for current shell
cat /proc/$$/cmdline # On Linux — exact binary path
# What shells are available?
cat /etc/shells
# What shell is a user configured to use?
grep "krav" /etc/passwd # Last field is login shell
Terminal window
# Windows — PowerShell or cmd?
echo %COMSPEC% # cmd.exe
$PSVersionTable # PowerShell (this variable only exists in PS)
Get-Host # PowerShell version info

Terminal window
# Change default login shell
chsh -s /bin/zsh
# Switch to a different shell temporarily
bash
zsh
sh
# Run a command in a specific shell
/bin/sh -c "echo running in sh"

Some shells are intentionally restricted:

ShellPurpose
/bin/rbashRestricted bash — no cd, no changing PATH, no redirections
/usr/bin/nologinDenies login entirely (for service accounts)
/bin/falseSame — immediately exits with failure
lshellConfigurable restricted shell (if installed)

Check /etc/passwd for accounts using nologin or false — these are service accounts that shouldn’t have interactive access.


After getting a reverse shell (e.g. from a web exploit), the shell is typically “dumb” — no tab completion, no arrow keys, no Ctrl+C handling, and clear doesn’t work.

Terminal window
# Python (most common method)
python3 -c 'import pty; pty.spawn("/bin/bash")'
python -c 'import pty; pty.spawn("/bin/bash")'
# Other methods if Python isn't available
script -qc /bin/bash /dev/null
echo os.system('/bin/bash') | perl
/bin/sh -i

After spawning a TTY:

Terminal window
# Background the reverse shell
Ctrl+Z
# In your local terminal — configure raw mode
stty raw -echo; fg
# Back in the reverse shell — set terminal type
export TERM=xterm
export SHELL=/bin/bash
# Optional: match terminal size
# In local terminal, run: stty size → e.g. "50 200"
stty rows 50 columns 200

Now you have: arrow keys, tab completion, Ctrl+C (won’t kill your shell), command history, and clear.

Terminal window
tty # Should show /dev/pts/X instead of "not a tty"
echo $TERM # Should be xterm or similar
stty -a # Show terminal settings

krav:x:1000:1000::/home/krav:/bin/bash
╰───── login shell
Terminal window
# List all unique shells in use
awk -F: '{print $7}' /etc/passwd | sort -u
# Find users with actual login shells
grep -v "nologin\|false" /etc/passwd