Shell script to append new lines to etc/hosts and Apache httpd-vhosts.conf in Mac OSX 10.6 - apache

I am using Mac OSX 10.6 and doing web development on it. I know a small amount about writing shell scripts, but I am not really versed in them as of yet.
What I would like to do is to write a shell script that will simply ask for a local site alias and the document directory and it will then append the new alias onto hosts with something like "127.0.0.1 mysite.local" on a new line at the bottom of etc/hosts.
Then the script would append Apache's httpd-vhosts.conf file with something like this:
<VirtualHost *:80>
DocumentRoot "/Repositories/myproject/mysite.com/trunk/htdocs"
ServerName mysite.local
ServerAlias mysite.localhost
</VirtualHost>
Then it would finally run the command to restart my Apache server. Now I know the terminal command to restart Apache, that is simple enough. I also know how to read in the site name and path from the user running the script. Such as below:
#!/bin/bash
read -p "New local site name: " site
read -p "Site path (ex:/Repositories/myproject/mysite.com/trunk/htdocs): " sitepath
What I don't know how to do is to append text to a file from terminal.
Any thoughts or helpful ideas?
Thanks,
Patrick

Untested, but it should work:
#!/bin/bash
read -p "New local site name: " SITE
read -p "Site path (ex:/Repositories/myproject/mysite.com/trunk/htdocs): " SITEPATH
#/etc/hosts
cp /etc/hosts /etc/hosts.original
echo -e "127.0.0.1\t${SITE}.local" >> /etc/hosts
#httpd-vhosts.conf
VHOSTSFILE="/etc/apache2/httpd-vhosts.conf"
cp $VHOSTSFILE ${VHOSTSFILE}.original
echo "<VirtualHost *:80>" >> $VHOSTSFILE
echo -e "\tDocumentRoot \"${SITEPATH}\"" >> $VHOSTSFILE
echo -e "\tServerName ${SITE}.local" >> $VHOSTSFILE
echo -e "\tServerAlias ${SITE}.localhost" >> $VHOSTSFILE
echo '</VirtualHost>' >> $VHOSTSFILE
#restart apache
>> redirects the output to the given file, appending the contents to the file. I’m also using -e to allow \t to be expanded to a tab character.
Note that you need to run this script with sudo. I've also included commands to backup the original files before modifying them, just in case.

I made some tweaks and did some extra stuff in the above answer, because this didn't work for me but it helped me to come up with another solution. This answer is only for Mac users.
First go in your /etc/apache2/httpd.conf and uncomment virtual host reference, which is this line Include /private/etc/apache2/extra/httpd-vhosts.conf
Now create a bash file I did that in my user’s home named as imran, you need to replace it with your username.
I placed it inside /Users/imran named as create_new_site.sh. I gave it executeable permissions, so it can be easily executed using chmod +x create_new_site.sh
Code for the script is as below:
#!/bin/bash
read -p "New local site name (prefix to .local): " SITE
SITEPATH=$SITE
sudo chmod -R a+w /Users/imran/Sites/web
SITEPATH="/Users/imran/Sites/web/${SITEPATH}"
mkdir -p $SITEPATH
#/etc/hosts
cp /etc/hosts /etc/hosts.original
echo -e "127.0.0.1\t${SITE}.local" >> /etc/hosts
#httpd-vhosts.conf
VHOSTSFILE="/etc/apache2/extra/httpd-vhosts.conf"
cp $VHOSTSFILE ${VHOSTSFILE}.original
echo "<VirtualHost *:80>" >> $VHOSTSFILE
echo -e "\tDocumentRoot \"${SITEPATH}\"" >> $VHOSTSFILE
echo -e "\tServerName ${SITE}.local" >> $VHOSTSFILE
echo '</VirtualHost>' >> $VHOSTSFILE
echo '<?php phpinfo();' > "${SITEPATH}/phpinfo.php"
sudo chmod -R a+w $SITEPATH
#restart apache
sudo apachectl restart
echo "All done! visit, let's visit http://${SITE}.local/phpinfo.php"
Once that is done you can start creating new sites using sudo ./create_new_site.sh. Remember that you need to be in your home directory, which you can go via cd ~ command. Now let's suppose you created a site with name test. You should be able to visit http://test.local/phpinfo.php to see your vhost working.

Related

Apache HTTP Server Docker Image - Cleaner configuration in Dockerfile wanted

I have this Dockerfile that does extra configuration of the official Apache HTTP Server Docker image. Is there a cleaner way to do this inside a Dockerfile? I'm very unfamiliar with Apache HTTP Server configuration and was just about able to cobble this together. (The reason for enabling mod_rewrite is because I use it in a .htaccess file in the htdocs folder)
ARG BUILD_DIR=/usr/src/app
FROM node:10.13.0-alpine as build
ARG BUILD_DIR
WORKDIR $BUILD_DIR
COPY package.json .
RUN npm install
COPY src src
COPY public public
RUN npm run build
FROM httpd:2.4.37-alpine
ARG BUILD_DIR
ENV SERVER_CONTAINER_NAME=server
COPY --from=build $BUILD_DIR/build htdocs
RUN sed -i 's,#\(LoadModule rewrite_module modules/mod_rewrite.so\),\1,g' conf/httpd.conf \
&& sed -i -e '/<Directory "\/usr\/local\/apache2\/htdocs">/,/<\/Directory>/{s/AllowOverride None/AllowOverride All/}' conf/httpd.conf \
&& sed -i 's,#\(LoadModule proxy_module modules/mod_proxy.so\),\1,g' conf/httpd.conf \
&& sed -i 's,#\(LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so\),\1,g' conf/httpd.conf \
&& echo 'ProxyRequests off' >> conf/httpd.conf \
&& echo 'ProxyPass /ws ws://${SERVER_CONTAINER_NAME}:8080/ws interpolate' >> conf/httpd.conf
It might be cleaner to keep the modified versions of those config files outside of the image, and then copy them into the container during the build.
Alternatively, you could put all the shell commands in a script. During the build, COPY the script into the container. At the end of the script add something like this:
exec /usr/sbin/apache2ctl -f /etc/apache2/apache2.conf -DFOREGROUND
to start your server. Then have docker invoke the script as
CMD [ "/MyScript.sh" ]

Find httpd.conf file location after it's been changed by -f flag

Httpd processes use a non-default configuration file if they are run with the -f flag.
For example
/home/myuser/apache/httpd-2.4.8/bin/httpd -f /confFiles/apache/2.4.8/apache.conf -k start
will use this configuration file: /confFiles/apache/2.4.8/apache.conf
I need to get this location and would rather not have to check for possible -f flags used to start httpd.
The answer here says to run /path/to/httpd -V and concatenate
-D SERVER_CONFIG_FILE="conf/httpd.conf"
with
-D HTTPD_ROOT="/etc/httpd"
to get the final path to the config file.
However, this path will not be the correct one if the -f flag is used to start the httpd process.
Is there a command that can get the config file that is actually being used by the process?
The answer you refer to mentions the paths httpd was compiled with, but as you say those can be manually changed with parameters.
The simple way to check is the command line, if process is called "httpd" (standard name), a simple ps will reveal the config file being used:
ps auxw | grep httpd
Or querying the server if server has mod_info loaded, in command line or with your favourite browser:
curl "http://yourserver.example.com/server-info?server" | grep -i "config file"
Note: mod_info should not be publicaly available for everyone to see.

monit: use hostname in logfile path

I am new to monit and want to use different logfile path for monit (not the default one)
set logfile /x/home/xxxx/yyyy/monit/monit-5.20.0/logs/monit_$HOST.log
In place of $HOST, I want the hostname where the monit is running.
Any idea how can we achieve this? Similarly, I wan to use the hostname for idfile and statefile as well.
Note: /x/home/xxxx/yyyy/monit/monit-5.20.0 is common mount for all machines and want to run monit on them. But don't want the same log file.
Finally I found the way to have hostname in the logfile, idfile and statsfile.
I created a wrapper script start.sh as follows and started the monit by passing control file, logfile, idfile and statsfile.
#!/bin/bash
BASEDIR=`dirname $0`
HOST=`hostname`
MONIT_BIN=$BASEDIR/bin/monit
CTRL_FILE=$BASEDIR/conf/monitrc
LOG_FILE=$BASEDIR/logs/monit_$HOST.log
PID_FILE=$BASEDIR/run/monit_$HOST.pid
STATS_FILE=$BASEDIR/run/.monit_$HOST.state
mkdir -p $BASEDIR/run
mkdir -p $BASEDIR/logs
touch $PID_FILE
touch $STATS_FILE
touch $LOG_FILE
nohup $MONIT_BIN -c $CTRL_FILE -l $LOG_FILE -p $PID_FILE -s $STATS_FILE &> /dev/null &

How does one use Apache in a Docker Container and write nothing to disk (all logs to STDIO / STDERR)?

I'm running Apache2 in a docker container and want to write nothing to the disk, writing logs to stdout and stderr. I've seen a few different ways to do this (Supervisord and stdout/stderr, Apache access log to stdout) but these seem like hacks. Is there no way to do this by default?
To be clear, I do not want to tail the log, since that will result in things being written to the disk in the container.
The "official" version checked into Docker Hub (https://hub.docker.com/_/httpd/) still write to disk.
Also, what do I need to do to stop Apache from failing when it tries to roll the logs?
One other thing - ideally, I'd really like to do this without another add-on. nginx can do this trivially.
I'm not positive that this won't mess with httpd's logging at all (e.g. if it tries to seek within the file), but you can set up symlinks from the log paths to /dev/stdout and /dev/stderr, like so:
ln -sf /dev/stdout /path/to/access.log
ln -sf /dev/stderr /path/to/error.log
The entry command to the vanilla httpd container from Docker Hub could be made to be something like
ln -sf /dev/stdout /path/to/access.log && ln -sf /dev/stderr /path/to/error.log && /path/to/httpd
According to the apache mailing list, you can just directly write to /dev/stdio (on Unix like systems) as that's just a regular ol' file handle. Easy! Pasting...
The most efficient answer depends on your operating system. If you're
on a UNIX like system which provides /dev/stdout and /dev/stderr (or
perhaps /dev/fd/1 and /dev/fd/2) then use those file names. If that
isn't an option use the piped output feature. For example, from my
config:
CustomLog "|/usr/sbin/rotatelogs -c -f -l -L
/private/var/log/apache2/test-access.log
/private/var/log/apache2/test-access.log.%Y-%m-%d 86400 "
krader_custom ErrorLog "|/usr/sbin/rotatelogs -c -f -l -L
/private/var/log/apache2/test-error.log
/private/var/log/apache2/test-error.log.%Y-%m-%d 86400"
Obviously you'll want to substitute another program for
/usr/sbin/rotatelogs in the example above that writes the data where
you want it to go.
https://mail-archives.apache.org/mod_mbox/httpd-users/201508.mbox/%3CCABx2=D-wdd8FYLkHMqiNOKmOaNYb-tAOB-AsSEf2p=ctd6sMdg#mail.gmail.com%3E
I know it's an old question, but I had this need today.
On an Alpine 3.6, the following instructions, in httpd.conf, are working:
Errorlog /dev/stderr
Transferlog /dev/stdout
I add them to my container this way:
FROM alpine:3.6
RUN apk --update add apache2
RUN sed -i -r 's#Errorlog .*#Errorlog /dev/stderr#i' /etc/apache2/httpd.conf
RUN echo "Transferlog /dev/stdout" >> /etc/apache2/httpd.conf
...
I adjusted config, as from the Dockerfile recipe of httpd, they use sed to adjust the config, to change ErrorLog and CustomLog as follows:
sed -ri ' \
s!^(\s*CustomLog)\s+\S+!\1 /proc/self/fd/1!g; \
s!^(\s*ErrorLog)\s+\S+!\1 /proc/self/fd/2!g; \
' /usr/local/apache2/conf/httpd.conf \
See https://github.com/docker-library/httpd/blob/master/2.4/Dockerfile (towards the end of the file)
You can send your ErrorLog to syslog directly, and you can send any CustomLog (access log) to any executable that reads from stdin. There are log aggregation tools, or you can again use syslog w/ e.g. /usr/bin/logger.
You could try using the dockerize tool. With that you could wrap the httpd-foreground command and redirect its log files to stdout/stderr (don't know exactly the httpd log file paths, simply adjust them to your needs):
CMD ["dockerize", "-stdout", "/var/log/httpd.log", "-stderr", "/var/log/httpd.err", "httpd-foreground"]
In addition to that you could grab that containers stdout/stderr then by specifying a syslog log driver and redirect them to the /var/log/syslog log file on the docker host:
docker run -d --log-driver=syslog ...

a2ensite 'Site: ___ does not exist' error, even with .conf file

System: Ubuntu 14.04 LAMP running on Parallels VM set up with Vagrant
I'm writing my first non-trivial shell script to add new web projects to a dev VM on my Mac laptop.
Create a default folder structure in /var/www/
Add a .conf vhost file to /etc/apache2/sites-available with the new domain replacing placeholders via sed
Enable the new site and restart apache
I've got the folders and files copying over and sed seems happy customizing my index.html and .conf vhost file, but a2ensite doesn't seem to see the .conf file in /etc/apache2/sites-available/
I test for its existence and even print a debug listing: ls -al /etc/apache2/sites-available/ | grep $CONFFILE before attempting to enable the site.
I've read here and elsewhere about the importance of having the .conf extension since Ubuntu 13 (or 14) which seems to be a very common issue. My vhost file has the .conf extension so this seems like a different issue.
Can anyone point me in the right direction? I haven't been able to find other postings with this particular problem.
My feeling is that I've got an error in my $CONFFILE variable expansion in the a2ensite command because the error does not show the .conf extension even though the directory listing does:
ERROR: Site /etc/apache2/sites-available/example-com-80 does not exist!
Edit:
After running a2ensite from the command line per Micheal's suggestion below, it seemed to parse fine, but still doesn't show the extension:
$ sudo a2ensite example-com-80.conf
Enabling site example-com-80.
To activate the new configuration, you need to run:
service apache2 reload
End Edit
Edit: Found answer
After searching with broader terms, a2ensite instead of Ubuntu 14.04 Vagrant etc, I found a two year old question where #raina77ow points out that a2ensite just wants the site name, not the whole path. Changing sudo a2ensite /etc/apache2/sites-available/$CONFFILE to sudo a2ensite $CONFFILE
makes the script work as intended. This also explains why my previous attempts to run a2ensite from the command line failed; I was running it from inside /var/www/templates/ and passing in the whole path to the .conf file.
Now, a stackoverflow question, how best should I indicate this is the solution with the limited reputation that I have? And give credit properly?
See edit above for solution
Console output with example.com:
$ ./newvhost
New Server Name with Top Level Domain: example.com
Validating: example.com
New DocumentRoot created: /var/www/example
Copying template structure
Creating: example-com-80.conf
-rw-r--r-- 1 root root 811 Feb 17 15:11 example-com-80.conf
Enabling site
ERROR: Site /etc/apache2/sites-available/example-com-80 does not exist!
newvhost script:
OLDIFS=$IFS
IFS="."
printf "New Server Name with Top Level Domain: "
read NEW_SUBDOMAIN NEW_TLD
IFS=$OLDIFS
NEW_FULL_NAME="$NEW_SUBDOMAIN.$NEW_TLD"
echo "Validating: $NEW_FULL_NAME"
if [[ "$NEW_TLD" != "com" && "$NEW_TLD" != "dev" ]] ; then
echo -e "\E[31;1mTLD must be com or dev! \033[0m"
exit 1
fi
if [ -d "/var/www/$NEW_SUBDOMAIN" ]; then
echo -e "\E[31;1mRoot directory /var/www/$NEW_SUBDOMAIN already exists!\033[0m"
exit 1
fi
mkdir /var/www/$NEW_SUBDOMAIN
if [ -d "/var/www/$NEW_SUBDOMAIN" ]; then
echo "New DocumentRoot created: /var/www/$NEW_SUBDOMAIN"
else
echo -e "\E[31;1mUnable to make directory\033[0m"
exit 1
fi
echo "Copying template structure"
cp /var/www/templates/structure/. /var/www/$NEW_SUBDOMAIN/ -R
sed -i "s/TEMPLATE/$NEW_FULL_NAME/g" /var/www/$NEW_SUBDOMAIN/index.html
CONFFILE="$NEW_SUBDOMAIN-$NEW_TLD-80.conf"
echo "Creating: $CONFFILE"
sudo cp /var/www/templates/vhost_template.conf /etc/apache2/sites-available/$CONFFILE
sudo sed -i "s/FULLNAME/$NEW_FULL_NAME/g" /etc/apache2/sites-available/$CONFFILE
sudo sed -i "s/DOMAINNAME/$NEW_SUBDOMAIN/g" /etc/apache2/sites-available/$CONFFILE
if [ -e "/etc/apache2/sites-available/$CONFFILE" ]; then
ls -al /etc/apache2/sites-available/ | grep $CONFFILE # DEGBUG Listing to doubly confirm $CONFFILE exists
echo "Enabling site"
sudo a2ensite /etc/apache2/sites-available/$CONFFILE
sudo apache2ctl graceful
fi
Thanks,
Any other suggestions for improving the script are very welcome as long as that doesn't run afoul with the terms of StackOverflow.
The answer, in short, is that a2ensite just wants the name of the site.conf and not the whole path to the file.
So sudo a2ensite example-com-80.conf
I found this in an earlier answer by #raina77ow.