How to Automate Shell Change (chsh) Without Password Prompt in Linux Scripts


2 views

When automating system setup scripts, running chsh -s /bin/zsh presents an immediate obstacle: the interactive password prompt. This breaks automation flows and requires manual intervention.

With sudo access, we have several approaches:

# Method 1: Using sudo directly
sudo chsh -s /bin/zsh $(whoami)

# Method 2: Pipe password to chsh (not recommended for security)
echo "yourpassword" | sudo -S chsh -s /bin/zsh

# Method 3: Edit passwd file directly (cleanest solution)
sudo sed -i 's|^$[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:$[^:]*|\1/bin/zsh|' /etc/passwd

When working without sudo privileges:

# Method 1: Using expect (requires package installation)
expect -c '
spawn chsh -s /bin/zsh
expect "Password:"
send "yourpassword\r"
expect eof
'

# Method 2: SSH key authentication
ssh user@localhost "chsh -s /bin/zsh"

For mass deployments, consider these approaches:

# Using ansible (recommended for enterprise)
- name: Change default shell
  ansible.builtin.user:
    name: "{{ item }}"
    shell: /bin/zsh
  loop: "{{ users_list }}"

# Using cloud-init (for cloud deployments)
users:
  - name: demo
    shell: /bin/zsh

Always evaluate these security aspects:

  • Avoid hardcoding passwords in scripts
  • Use SSH keys instead of password authentication
  • Consider temporary sudo rules with NOPASSWD
  • Log all shell change activities

After changing shells, verify with:

# Check current user
grep "^$(whoami):" /etc/passwd | cut -d: -f7

# Test new shell
sudo -u username /bin/zsh -c "echo $SHELL"

When automating machine setup scripts, the chsh -s /bin/zsh command presents a common roadblock - it interactively prompts for the user's password. This breaks automated workflows that need to run without human intervention.

If you have sudo privileges, these approaches work best:

# Method 1: Direct sudo execution
sudo chsh -s /bin/zsh $(whoami)

# Method 2: Edit /etc/passwd directly
sudo usermod -s /bin/zsh $(whoami)

# Method 3: Using expect (for non-sudo environments)
expect <<EOF
spawn chsh -s /bin/zsh
expect "Password:"
send "your_password\r"
expect eof
EOF

For environments where sudo isn't available:

# SSH key-based solution (for remote setups)
ssh user@host 'echo "password" | sudo -S chsh -s /bin/zsh user'

# Using chpasswd (requires root)
echo "username:/bin/zsh" | sudo chpasswd -e

For provisioning multiple machines, consider modifying the default shell system-wide:

# Change default for new users
sudo sed -i 's|SHELL=.*|SHELL=/bin/zsh|' /etc/default/useradd

# Docker/container approach
RUN apt-get update && apt-get install -y zsh \
    && chsh -s $(which zsh) \
    && rm -rf /var/lib/apt/lists/*

When automating password input:

  • Never hardcode passwords in scripts
  • Use environment variables or secret managers
  • Consider SSH certificate authentication instead
  • Set strict permissions on any files containing credentials