Shell Script Breaks with Heredoc in PHPmyadmin Installation – Troubleshooting Guide

crashhere-documentphpmyadminpromptshell-script

I can run the following script just fine using the traditional way of:

cd ~ && vi script.sh [PASTE SCRIPT INSIDE] && chmod +x script.sh && ./script.sh && rm -rf script.sh

Yet, if I execute the exact same script with Heredoc (to just paste and execute directly from Bash prompt), then the script will be executed only partially, and will break before the end.

For example, ere's what happens when I run the following script with Heredoc:

The PHPmyadmin install interface fuses with the CLI, while the CLI itself loses almost any capability besides documenting standard input:

enter image description here

The script (with my Heredoc):

bash << 'EOT0'

#!/bin/bash -x

# Setup LAMP environment with enabled mod rewrite:
cd ~
apt-get install lamp-server^ -y
a2enmod rewrite
cat << EOF >> /etc/apach2/apache2.conf
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
EOF
service apache2 restart

# Setup Webmin and some dependencies:
apt-get install unzip perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl apt-show-versions python -y
wget http://prdownloads.sourceforge.net/webadmin/webmin_1.810_all.deb
dpkg --install webmin_1.810_all.deb
apt-get -f install
sed -i 's/ssl=1/ssl=0/g' /etc/webmin/miniserv.conf
/etc/init.d/webmin restart

# Cron tasks:
echo -e "\07" && echo -e "\007" # Choose Nano (2) and do ^x.
USER=benqzq
crontab -u $USER -l 2>/dev/null
cat <<- 'EOF'
0 8 * * *  tar -zcvf /home/USERNAME/backups/files/www-html-$(date +\%F-\%T-).tar.gz /var/www/html
0 8 * * *  find /home/USERNAME/backups/files/* -mtime +30 -exec rm {} \;

0 8 * * *  mysqldump -u root -PASSWORD --all-databases > /home/USERNAME/backups/mysql/alldb_backup.sql
1 8 * * *  tar -zcvf /home/USERNAME/backups/mysql/alldb_backup-$(date +\%F-\%T-).sql.tar.gz /home/USERNAME/backups/mysql/alldb_backup.sql
2 8 * * *  rm /home/USER/backups/mysql/alldb_backup.sql
2 8 * * *  find /home/USERNAME/backups/mysql/* -mtime +30 -exec rm {} \;
EOF
crontab -e
USER=root

# Setup PMA:
echo -e "\07" && echo -e "\007"
apt-get install phpmyadmin php-mb\string php-gettext -y
phpenmod mcrypt && phpenmod mbstring
bash -c "echo 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf"
systemctl reload apache2.service

# Setup Fail2Ban:
apt-get install fail2ban -y

# Secure PMA HTTP authentication from BFAs with Fail2Ban:
cat << EOF > /etc/fail2ban/filter.d/phpmyadmin.conf
[Definition]
denied = mysql-denied|allow-denied|root-denied|empty-denied
failregex = ^<HOST> -.*(?:%(denied)s)$
ignoreregex =
EOF
cat << EOF >> /etc/fail2ban/jail.local
[phpmyadmin]
enabled = true
port = http,https
filter = phpmyadmin
logpath = /var/log/apache2/phpmyadmin_access.log
EOF

service  apache2 reload
service fail2ban reload
reboot

# Comment1
# Comment2
# Comment3
# ...

EOT0

Update for Stéphane Chazelas

enter image description here

Best Answer

You're doing:

bash << 'EOT'
some-command-that-reads-stdin
EOT

But some-command-that-reads-stdin's stdin will be that here document as well, as it is started by bash so inherits the same stdin.

You could do:

bash /dev/fd/3 3<< 'EOT'
some-command-that-reads-stdin
EOT

So stdin is left untouched, and bash gets the code from that here document on another fd.

Related Question