mcbain83
mcbain83

Reputation: 512

Shell out into zsh and execute commands from bash script

I'm trying my hand a little virtualisation, so I've been using vagrant to provision a centos7 vm and now I am configuring it with applications.

My vagrant config runs a bootstrap.sh file which is a bash script, in it I install zsh, then I want to configure it as per https://github.com/sorin-ionescu/prezto . step 1 is launch zsh then run some commands.

This is the code I have at the moment.

echo "Installing zsh"
yum install -y zsh

echo "Configure zsh"
# touch /home/vagrant/.zshrc
exec /usr/bin/zsh
git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
chsh -s /bin/zsh

I want this to be the default shell when I ssh into the VM. It does not appear to be working, there are no errors with the vagrant up step so I just want to know if this is possible and if this seems correct?

Thanks

Upvotes: 3

Views: 2554

Answers (2)

Charles Duffy
Charles Duffy

Reputation: 295242

exec zsh replaces your shell with zsh -- but doesn't in any way tell that instance of zsh to pick up at the same point in execution, or even to run the same script that the bash invocation was previously executing at all.

One easy fix is to feed the rest of your script to zsh via a heredoc:

/usr/bin/zsh <<'EOF'
git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
chsh -s /bin/zsh
EOF

Upvotes: 5

Adaephon
Adaephon

Reputation: 18329

exec /usr/bin/zsh replaces the running script with a new zsh process. Everything after that is not executed.

You have essentially two options:

  1. Put the stuff specific to zsh into a separate script and run that with /usr/bin/zsh:

    vagrant:

    echo "Installing zsh"
    yum install -y zsh
    
    echo "Configure zsh"
    # touch /home/vagrant/.zshrc
    git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
    
    # run external script
    /usr/bin/zsh /home/vagrant/install-prezto.zsh
    
    chsh -s /bin/zsh
    

    /home/vagrant/install-prezto.zsh:

    setopt EXTENDED_GLOB
    for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
      ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
    done
    
  2. Modify the script so that zsh is not needed for the installation:

    echo "Installing zsh"
    yum install -y zsh
    
    echo "Configure zsh"
    # touch /home/vagrant/.zshrc
    git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
    
    # use find instead of *zsh* to link files
    find "${ZDOTDIR:-$HOME}/.zprezto/runcoms/" -maxdepth 1 -type f -! -name README.md --exec ln -s {} "${ZDOTDIR:-$HOME}/" +
    
    chsh -s /bin/zsh
    

Upvotes: 3

Related Questions