Review compatibility, readability, good code standards, security.
This is for development server, where webmaster uses GUI fo IDE and fine way to create quickly apache2 virtualhost using GUI but fallback to text interface is present. Second review of script with applying previous review and adding more features.
I`ll post code parts fist, then whole script and git link to it.
If user runs script without terminal I need to notify him somehow about errors. xmessage
provided with X but looks ugly, but looks compatible. May be suggested other way - portable and better looking. User will always get error output in terminal what's fine. In any case if using GUI user suggested to install zenity
as a main gui tool of script - that will be message from xmessage
.
notify_user () {
echo "$1" >&2
[ -t 0 ] || if type -p notify-send >/dev/null; then notify-send "$1"
else xmessage -buttons Ok:0 -nearmouse "$1" -timeout 10; fi
}
Is following exit 1
exits function or script? I guess only function. That's why empty input not break script, at least tested in giu. How to rewrite this function to handle empty input as error to break
script?
get_virtual_host() {
if [ -t 0 ]; then
read -p "Create virtualhost (= Folder name,case sensitive)" -r host
else
host=$(zenity --forms --add-entry=Name --text='Create virtualhost (= Folder name,case sensitive)')
fi
case "$host" in
"") notify_user "Bad input: empty" ; exit 1 ;;
*"*"*) notify_user "Bad input: wildcard" ; exit 1 ;;
*[[:space:]]*) notify_user "Bad input: whitespace" ; exit 1 ;;
esac
echo "$host"
}
host=$(get_virtual_host)
What is better, hardcode some config string variables, allow input parameters[with leak verification], or make install script what hardcodes input parameters for server, also make .desktop file? I think hardcode is good, as one could hardcode and make permissions to edit and execute. Looks following:
webmaster="leonid" # user who access web files. group is www-data
maindomain=".localhost" # domain for creating subdomains, leading dot required
serveradmin="webmaster@localhost" # admin email
webroot="/home/${webmaster}/Web/" # root folder where subfolders for virtualhosts created
Full script: (git: https://github.com/LeonidMew/CreateVirtualHost)
#!/bin/bash
webmaster="leonid" # user who access web files. group is www-data
maindomain=".localhost" # domain for creating subdomains, leading dot required
serveradmin="webmaster@localhost" # admin email
webroot="/home/${webmaster}/Web/" # root folder where subfolders for virtualhosts created
a2ensite="050-" # short prefix for virtualhost config file
apachehost="/etc/apache2/sites-available/${a2ensite}" # prefix for virtualhost config file
tmphost=$(mktemp) # temp file for edit config
trap "rm $tmphost" EXIT # rm temp file on exit
notify_user () {
echo "$1" >&2
[ -t 0 ] || if type -p notify-send >/dev/null; then notify-send "$1"; else xmessage -buttons Ok:0 -nearmouse "$1" -timeout 10; fi
}
if [ -t 0 ];then
usegui=""
else
if ! type -p zenity >/dev/null;then
notify_user "Use terminal or install zenity for gui. '$ sudo apt install zenity'"
exit 1
else
usegui="yes"
fi
fi
# if [ "$(id -un)" == "root" ]
# then
# notify_user "You should not run this script as root but as user going to edit web files."
# exit 1
# fi
get_virtual_host() {
if [ -t 0 ]; then
read -p "Create virtualhost (= Folder name,case sensitive)" -r host
else
host=$(zenity --forms --add-entry=Name --text='Create virtualhost (= Folder name,case sensitive)')
fi
case "$host" in
"") notify_user "Bad input: empty" ; exit 1 ;;
*"*"*) notify_user "Bad input: wildcard" ; exit 1 ;;
*[[:space:]]*) notify_user "Bad input: whitespace" ; exit 1 ;;
esac
echo "$host"
}
host=$(get_virtual_host)
hostfile="${apachehost}${host}.conf" # apache virtualhost config file
dir="${webroot}${host}" # folder used as document root for virtualhost
# virtualhost template
cat >"$tmphost" <<EOF
<VirtualHost *:80>
ServerAdmin $serveradmin
DocumentRoot $dir
ServerName ${host}${maindomain}
ServerAlias ${host}${maindomain}
<Directory "$dir">
AllowOverride All
Require local
</Directory>
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
LogLevel error
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
EOF
if [ ! -z "$usegui" ];then
# edit virtualhost config
text=$(zenity --text-info --title="virtualhost config" --filename="$tmphost" --editable)
if [ -z "$text" ]
then
# cancel button pressed
exit 0
fi
echo "$text" > "$tmphost"
else
# edit virtualhost config
editor=${VISUAL:-$EDITOR}
if [ -z "$editor" ];then
if type -p nano >/dev/null;then editor="nano"; fi
fi
if [ -z "$editor" ];then
if type -p vim >/dev/null;then editor="vim"; fi
fi
if [ -z "$editor" ];then
echo "edit '$tmphost' to your liking, then hit Enter"
read -p "I'll wait ... "
else
"$editor" "$tmphost"
fi
fi
# probably want some validating here that the user has not broken the config
# apache will not reload config if incorrect
getsuperuser () {
if [ ! -z "$usegui" ];then
echo "pkexec"
else
echo "sudo"
fi
}
notify_user "execute root commands with $(getsuperuser) to create virtualhost"
$(getsuperuser) /bin/bash <<EOF
mkdir -p "$dir"
chown ${webmaster}:www-data "$dir"
chmod u=rwX,g=rX,o= "$dir"
cp "$tmphost" "$hostfile"
chown root:root "$hostfile"
chmod u=rw,g=r,o=r "$hostfile"
a2ensite "${a2ensite}${host}.conf"
systemctl reload apache2
EOF
notify_user "Virtualhost added. Apache2 reloaded."