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

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.

Related

Is it possible to tell ansible not to use ~/.ssh/config?

My ~/.ssh/config file is interfering with ansible, I use a lot of abbreviations in there to make my life easier when logging onto servers.
for example in:
Host te*
HostName %h.example.com
User test
In my ansible hosts file I have:
[servers]
te1.exmaple.com
te2.example.com
which means when I run ansible, the connection will fail because it will use my ssh config file and try to connect to te1.example.com.example.com.
I know I could modify ansible hosts to just be te1 and let ssh config add the rest of the domain, but I know that other members of my team don't have their .ssh/config set up like me so this isn't really an option, and tbh is the easy route which will end up causing problems for others.
Is there a way in ansible to tell it not to use mine or anyone else .ssh/config file?
You can use the ANSIBLE_SSH_ARGS parameter in ansible.cfg for that. The required ssh parameter is -F configfile which has the following meaning:
-F configfile
Specifies an alternative per-user configuration file. If a
configuration file is given on the command line, the system-wide
configuration file (/etc/ssh/ssh_config) will be ignored. The default
for the per-user configuration file is ~/.ssh/config.
So your ANSIBLE_SSH_ARGS with the defaults in in ansible.cfg would then look like this:
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -F /dev/null
ssh -F allows you to specify "an alternative per-user configuration file".
-F configfile
Specifies an alternative per-user configuration file. If a configuration file is given on the command line, the
system-wide configuration file (/etc/ssh/ssh_config) will be ignored. The default for the per-user configuration
file is ~/.ssh/config.
In Ansible you can configure it by ANSIBLE_SSH_ARGS.
For example in ansible.cfg you can set it to any file that fits your needs.
[ssh_connection]
ssh_args = -F ...
Or, you might want to create a separate user (let's say ansible-admin) set her ~/.ssh/config and use it to run ansible.
This is what worked for me in the end. I added this to my ansible.cgf file.
[all:vars] ansible_ssh_common_args = '-F /dev/null'
Thanks to all who answered :)

How to add EnvironmentFile directive to systemctl using Docker with centos7/httpd base image

I am not sure if this is possible without creating my own base image, but I use environment variables in /etc/environment on our servers and typically make them accessible to apache by doing the following:
$ printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
$ mkdir /usr/lib/systemd/system/httpd.service.d
$ printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
$ systemctl daemon-reload
$ systemctl restart httpd
$ reboot
The variables are then available in any PHP calls to getenv('HTTP_VAR1'); and etc. However, in running this from a docker file I get dbus errors on the systemctl commands. Without the systemctl commands it seems the variables are not available to apache as it seems the new EnvironmentFile directive doesn't take effect. My docker file snippet:
FROM centos/httpd:latest
RUN printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
RUN mkdir /usr/lib/systemd/system/httpd.service.d &&\
printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
RUN systemctl daemon-reload &&\
systemctl restart httpd
COPY entrypoint.sh /entrypoint.sh
So I happened upon the answer to the issue today. It seems that systemd drops backslashes inside single quotes, but it may effect double-quotes too from what I saw in testing. I found the systemd development mailing list thread from April 2014 where patching the issue was being discussed. It seems as though the fix never made it in. So we have to work around it.
In attempting to work around it I noticed some issues with actually reading the variables at all. It seemed as though either Apache or php-cli would get the correct variables, and sometimes not at all, it took a bit of sleuthing to figure out what was going on. Then I started reading into the systemd's EnvironmentFile directive to see if there was more to gain from the docs. It turns out it does not evaluate bash so export won't work. It expects a text file with variable assignments and herein lies one of the main issues that might keep this from being resolved.
I then devised a workable solution. Utilizing systemd's ExecStartPre directive I am able to run a script on startup of the httpd service. I then read in the environment file and write a new plain text one that will then be used by httpd's systemd unit. Here is the code:
Firstly, I moved my variables to /etc/profile.d/ directory rather than /etc/environment file.
file: /etc/profile.d/environment.sh
This is where we store all our environment variables, this gets easily sourced on all interactive shell logins. In the rarer cases where we need to have these variables available non-interactively we can either provide --login flag to /bin/bash or source it manually.
export HTTP_VAR1=var1-value-with-a-back\slash
export HTTP_VAR2=var2-value
file: /usr/lib/systemd/system/httpd.service.d/environment.conf
Our drop-in unit file to extend how the httpd service works. I add in a script that runs before httpd starts up. This gets ran on all httpd restarts and starts. The script that runs generates a plain text file at /etc/profile.d/environment.env which we subsequently tell systemd to load as an EnvironmentFile.
[Service]
ExecStartPre=/usr/bin/bash -c "/usr/local/bin/generate-plain-environment-file"
EnvironmentFile=/etc/profile.d/environment.env
file: /usr/local/bin/generate-plain-environment-file
Here is the script I am using, I whipped this together really fast, I really don't think it is that robust and it could be better. It just removes the export from the beginning of the lines and then escapes any backslashes since systemd drops single backslashes. A more proper solution might be to use bash to evaluate each line and obtain the variable value in case of usage of variables or other bash in the actual bash variables, then output them as plain text name=value assignments, however this is not part of my use-case so I didn't bother.
#!/bin/bash
cd /etc/profile.d/
rm -rf "./environment.env"
while IFS='' read -r line || [[ -n "$line" ]]; do
echo $(echo "${line}" | sed 's/^export //' | sed 's/\\/\\\\/g') >> "./environment.env";
done < "./environment.sh"
file: /etc/profile.d/environment.env
This is the resulting file generated by the described script.
HTTP_VAR1=var1-value-with-a-back\\slash
HTTP_VAR2=var2-value
Conclusion is that the I now have two files with the same thing in them but I only need to maintain the one, the other is generated each time we restart httpd. Also, we fix the backslash issue in the process. Hurray!

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 ...

How to shorten an inittab process entry, a.k.a., where to put environment variables that will be seen by init?

I am setting up a Debian Etch server to host ruby and php applications with nginx. I have successfully configured inittab to start the php-cgi process on boot with the respawn action. After serving 1000 requests, the php-cgi worker processes die and are respawned by init. The inittab record looks like this:
50:23:respawn:/usr/local/bin/spawn-fcgi -n -a 127.0.0.1 -p 8000 -C 3 -u someuser -- /usr/bin/php-cgi
I initially wrote the process entry (everything after the 3rd colon) in a separate script (simply because it was long) and put that script name in the inittab record, but because the script would run its single line and die, the syslog was filled with errors like this:
May 7 20:20:50 sb init: Id "50" respawning too fast: disabled for 5 minutes
Thus, I got rid of the script file and just put the whole line in the inittab. Henceforth, no errors show up in the syslog.
Now I'm attempting the same with thin to serve a rails application. I can successfully start the thin server by running this command:
sudo thin -a 127.0.0.1 -e production -l /var/log/thin/thin.log -P /var/run/thin/thin.pid -c /path/to/rails/app -p 8010 -u someuser -g somegroup -s 2 -d start
It works apparently exactly the same whether I use the -d (daemonize) flag or not. Command line control comes immediately back (the processes have been daemonized) either way. If I put that whole command (minus the sudo and with absolute paths) into inittab, init complains (in syslog) that the process entry is too long, so I put the options into an exported environment variable in /etc/profile. Now I can successfully start the server with:
sudo thin $THIN_OPTIONS start
But when I put this in an inittab record with the respawn action
51:23:respawn:/usr/local/bin/thin $THIN_OPTIONS start
the logs clearly indicate that the environment variable is not visible to init; it's as though the command were simply "thin start."
How can I shorten the inittab process entry? Is there another file than /etc/profile where I could set the THIN_OPTIONS environment variable? My earlier experience with php-cgi tells me I can't just put the whole command in a separate script.
And why don't you call a wrapper who start thin whith your options?
start_thin.sh:
#!/bin/bash
/usr/local/bin/thin -a 127.0.0.1 -e production -l /var/log/thin/thin.log -P /var/run/thin/thin.pid -c /path/to/rails/app -p 8010 -u someuser -g somegroup -s 2 -d start
and then:
51:23:respawn:/usr/local/bin/start_thin
init.d script
Use a script in
/etc/rc.d/init.d
and set the runlevel
Here are some examples with thin, ruby, apache
http://articles.slicehost.com/2009/4/17/centos-apache-rails-and-thin
http://blog.fiveruns.com/2008/9/24/rails-automation-at-slicehost
http://elwoodicious.com/2008/07/15/nginx-haproxy-thin-fastcgi-php5-load-balanced-rails-with-php-support/
Which provide example initscripts to use.
edit:
Asker pointed out this will not allow respawning. I suggested forking in the init script and disowning the process so init doesn't hang (it might fork() the script itself, will check). And then creating an infinite loop that waits on the server process to die and restarts it.
edit2:
It seems init will fork the script. Just a loop should do it.

relocate apache's configuration files

is there a chance to use different location for apache's config files (on Windows)? Other than having to compile it myself and setting the proper #define HTTPD_ROOT value.
Thx rezna
This can be done by specifying the -f option when installing apache as a service on Windows.
The -f option accepts the location of the configuration file. For example, if your command to install the service was
httpd.exe -k install -n "MyServiceName"
Add -f "c:\files\my.conf", with your configuration file instead, like so:
httpd.exe -k install -n "MyServiceName" -f "c:\files\my.conf"
See the Apache manual for more information.