Recompiling Nginx - compilation

I have nginx running now on a live website, but I need to recompile it to add some extra features. The commands i use are.
make clean
./configure -- BLA BLA BLA
make
make install
Just to confirm, I don't need to stop nginx, until I run 'make install' right? The 'make' command takes the longest, I just want to be 100% sure I dont need to stop Nginx sooner.
So to confirm, this would mean really just a second or two downtime.
make clean
./configure -- BLA BLA BLA
make
/etc/init.d/nginx stop
make install
/etc/init.d/nginx start

You are right, make just do the linking and compilation, while make install will install it on the system

You don't need to have a downtime. You compile and replace the executable.
Then you trigger nginx to spawn a new master.
The process is explained here:
http://nginx.org/en/docs/control.html#upgrade
New Version - Master - start:
kill -s USR2 `cat /var/run/nginx.pid`
Old Version - Worker - stop:
kill -s WINCH `cat /var/run/nginx.pid.oldbin`
Old Version - Master - stop:
kill -s QUIT `cat /var/run/nginx.pid.oldbin`
If you want to go back to the older version:
Old Version - Worker - start:
kill -s HUP `cat /var/run/nginx.pid.oldbin`
New Version - Master - stop:
kill -s QUIT `cat /var/run/nginx.pid`
If you get an error that the file cannot be replaced your compile options are wrong.
--sbin-path=/usr/sbin/nginx

Related

Docker: How to ADD a service via ENV variables?

I have built a Docker Cron Environment to run Cronjobs based on alseambusher/crontab-ui using alpine:3.15.3 & it works great.
For it to work I have had to install a number of things via the Dockerfile, editing it & adding python so it could run a python script, perl for another service, openssl so I could use a Self-signed certificate, etc.
As it stands the Container is a lot bigger, which is fine, but if I am to share the container others won't necessarily want or need the services I have added & will likely need other that I haven't.
I would like to be able to add a command in the ENV of a Docker Compose to add services at startup without having to do a full build each time. I'm sure it would be simpler to add build:>args: & have it rebuild the container each startup, but my goal is to have it add to an image only the services that each user needs & declares in the Docker-Compose with no need to have the files for the build on the system.
I know this will mean a longer startup depending on the services, I'm okay with that.
I know it's normal to run cron on the host & have it call into containers, but cron on Windows WSL has to be manually started every time the WSL starts & is easy to forget about & can't really be automated aside from on startup, & I'd like to do this entirely inside Docker.
How can I add an ENV like SERVICE_INSTALL to have it run in BASH (which is already added in the Dockerfile & present at /bin/bash) at container startup?
Ideally I'd like to be able to add multiple SERVICE_INSTALL lines if at all possible.
Example:
SERVICE_INSTALL1='apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python'
SERVICE_INSTALL2='python3 -m ensurepip'
SERVICE_INSTALL3='apk add --no-cache perl perl-html-parser perl-http-cookies perl-lwp-useragent-determined perl-json perl-json-xs'
Or, if nothing else:
SERVICE_INSTALL=apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python && perl perl-html-parser perl-http-cookies perl-lwp-useragent-determined perl-json perl-json-xs && && wget && curl && nodejs && npm
but then that leaves the problem of installing things through pip or npm.
I have tried adding a command: to the Docker-Compose but every variation I have tried does not work. I'm also concerned with this method as from my understanding a command: replaces the startup script in the container, not adds to it, so that is not ideal, regardless, it doesn't seem like an install command: is possible anyway
I have tried: (Each as a single command: not together)
command:
- BASH apk --update add openssl
- /bin/bash apk --update add openssl
- BASH RUN apk --update add openssl
- /bin/bash RUN apk --update add openssl
- sh apk --update add openssl
- /bin/sh apk --update add openssl
- apk --update add openssl
Each ends with a message along the lines of Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/bin/bash run apk --update add openssl": stat /bin/bash run apk --update add openssl: no such file or directory: unknown
UPDATE: I discovered a few things trying to get this to work
for command: to work there needs to not be any - before it
anything, even on multiple lines, is considered a single command essentially as though they were all on the same line & have to be separated with an &&
it will repeat the command or show the error of it failing to execute the command & not continue to next until it is completed.
for example the command mkdir -p /test leaves no logs, but the container never actually starts. While portainer says it's running trying to bash into it gives a is restarting, wait until the container is running message
mkdir "-p /test" repeats this message
mkdir: unrecognized option:
BusyBox v1.34.1 (2022-02-02 18:21:20 UTC) multi-call binary.
Usage: mkdir [-m MODE] [-p] DIRECTORY...
Create DIRECTORY
-m MODE Mode
-p No error if exists; make parent directories as needed
3 times 3-4 seconds apart, them 7 seconds, then 8 seconds, then 15 seconds, 27 seconds, 53 seconds, then hits a minute & continues to grow a few seconds each try.
It also returns the same wait for the container to be running message when trying to bash in
mkdir -p "/test" seems to be the correct formatting, it appears to work but leaves no logs & when attempting to bash in it connects, shows the terminal, then exits, attempting to reconnect shows the same container is restarting message, likely because the container stopped once the command was finished & is set to restart: always. commenting out the restart command the container exits.
mkdir -p "/test" followed by a new line with supervisord -c /etc/supervisord.conf (the default start command) has mkdir reporting mkdir: unrecognized option: c
adding "supervisord -c /etc/supervisord.conf" leaves no logs & a restarting container.
reversing the order, with supervisord -c /etc/supervisord.conf 1st has supervisord reporting the error Error: positional arguments are not supported: ['mkdir', '-p', '/test'] For help, use /usr/bin/supervisord -h
bash -c "supervisord -c /etc/supervisord.conf with a new line & && mkdir -p /test with a new line & && mkdir -p /test2" runs with a working container, but no directories created
reversing the order seems to work & creates the directories, with a running container
command:
bash -c "mkdir -p /test
&& mkdir -p /test2
&& supervisord -c /etc/supervisord.conf"
Which indicates that it will run them in order, but only proceeds to the next after the one finishes.
a test confirmed that the same can be done with other dependencies so long as the initial startup is last. I'd rather have the container start 1st, then install the dependencies while it is running as they are not required for the container itself to run, but rather are added for use in the cronjobs that will be running on a schedule, so if the container starts & the dependencies cannot be used for the 1st 2, 3, even 5 or 10 minutes that might only affect their 1st attempt if it happens to be in that time.
This is alright, I now understand better how the command: option works, but it still requires users to know & properly include the default start command. The command: options are also a lot more particular & easy to get wrong, while ENV variables are something every docker user knows, has experience with, & is simpler to implement

udev rule not working correctly, probably escaping issue

I try to run an udev rule once a mount is ready on a Vagrant box:
SUBSYSTEM=="bdi",ACTION=="add",RUN+="/usr/bin/screen -m -d bash -c 'sleep 5; cd /vagrant/; sudo -E su -c "pm2 start daemon.json" vagrant;'"
But the command isn't running properly, since the pm2 doesn't start.
When I execute /usr/bin/screen -m -d bash -c 'sleep 5; cd /vagrant/; sudo -E su -c "pm2 start daemon.json" vagrant;' manually it does work.
Any ideas?
The nested quotes are surely part of the problem, but the bigger problem is written in the udev manual:
This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device. Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.
So your approach has to be changed. However, let’s suppose the command pm2 start daemon.json is appropriately short-running: your question is interesting anyway, because similar quote-nesting problems arise often. So please consider the rest of this answer as an example for the general case.
Instead of going mad with the correct escaping sequences, you can just write
RUN+="/usr/bin/screen -m -d bash -c 'sleep 5; cd /vagrant/; sudo -E -u vagrant pm2 start daemon.json"
An even simpler solution might be
RUN+="/usr/bin/screen -m -d /usr/local/bin/start_vagrant_daemon"
where /usr/local/bin/start_vagrant_daemon is executable and has the following content
#!/bin/bash
sleep 5
cd /vagrant/
sudo -E -u vagrant pm2 start daemon.json
Both solutions require setting up the correct sudo authorizations by editing /etc/sudoers or (better) writing them in a new file /etc/sudoers.d/vagrant_daemon after enabling includedir /etc/sudoers.d in /etc/sudoers.

How could I run a shell script with delay

I basically want to run a script which is a server but with 10 second delay, it is because I need some stuff to run before this script.
The server is located in the folder /etc/init.d but basically to make it work I go to that path using the command line and I have to restart the server typing:
sudo ./znodejs.sh stop
And then I start the server again:
sudo ./znodejs.sh start
I would like to know if there is any way to run those commands with a delay.
In order to make a script run on startup first make it executable:
$ sudo chmod 755 /etc/init.d/znodejs.sh
Then you can register the script to be run at startup:
$ sudo update-rc.d znodejs.sh defaults
(Edit)
original answer:
the sleep command sill pause for a given number of seconds:
sudo ./znodejs.sh stop
sleep 10
sudo ./znodejs.sh start
The standard unix command for sleeping is called
sleep
to wait a second, use
sleep 1

How to restart nginx on OS X

I'm using nginx on OS X 10.8. Freshly installed nginx but can't find a way to restart nginx except kill nginx_pid say kill 64116. Wondering if there are better ways to restart nginx.
Found some methods on Google and SO but didn't work:
nginx -s restart
sudo fuser -k 80/tcp ; sudo /etc/init.d/nginx restart
The error message for nginx -s restart is
nginx: [error] open() "/usr/local/var/run/nginx.pid" failed (2: No such file or directory)
Sometimes also get this error msg:
nginx: invalid option: "-s restart"
Try running sudo nginx before starting nginx.
To reload config files:
sudo nginx -s reload
To fully restart nginx:
sudo nginx -s quit
sudo nginx
Details
There is no restart signal for nginx. From the docs, here are the signals that the master process accepts:
SIGINT, SIGTERM Shut down quickly.
SIGHUP Reload configuration, start the new worker process with a new configuration, and gracefully shut down old worker processes.
SIGQUIT Shut down gracefully.
SIGUSR1 Reopen log files.
SIGUSR2 Upgrade the nginx executable on the fly.
SIGWINCH Shut down worker processes gracefully.
Presumably you could send these signals to the process id manually, but the nginx command has the flag nginx -s <signal> that sends signals to the master process for you. Your options are:
stop SIGTERM
quit SIGQUIT
reopen SIGUSR1
reload SIGHUP
No need to futz with the pid manually.
Edit: just realized much of this info was already in comments on the other answers. Leaving this here anyway to summarize the situation.
What is your nginx pid file location? This is specified in the configuration file, default paths specified compile-time in the config script. You can search for it as such:
find / -name nginx.pid 2>/dev/null (must issue while nginx is running)
Solution:
sudo mkdir -p /usr/local/var/run/
ln -s /current/path/to/pid/file /usr/local/var/run/nginx.pid
$ sudo nginx -c /usr/local/etc/nginx/nginx.conf
$ sudo nginx -s reload
Source Link: https://blog.csdn.net/github_33644920/article/details/51733436
Try this:
sudo nginx -s stop
followed by a:
sudo nginx
It seems that nginx keeps track of its state, to if you stop it twice, it will complain. But the above worked for me.
I do it like this:
First kill the progress
ps aux | grep nginx
kill -9 {pid}
Then start nginx
nginx
It works!
As a future resource, you can consult http://wiki.nginx.org/CommandLine
Nginx probably runs as root, so you will need to run a variant of the following command to affect it.
sudo nginx -s stop | reload | quit | reopen
There is usually not much reason to restart Nginx like Apache would need. If you have modified a configuration file, you may just want to the reload option.
check if this directory exists:
/usr/local/var/run
this error can occurs when nginx try to initialise pid file in
localisation that doesn't exist.
There is a bug here. Depending on whether nginx is running while you modify/restart apache and/or modify nginx configs it is possible for this file (which is essentially just a process ID pointer) to be destroyed.
When you attempt to send any signal to nginx like
nginx -s quit;
nginx -s stop;
nginx -s reload;
nginx uses this file to reference the ID of the process to which it needs to send the signal. If the file isn't there the link between the active running process of nginx & the cli app is effectively broken.
I actually ended up in a state where two nginx processes were running simultaneously so killed both.
To work around this, you can either Force the termination of existing nginx processes via Activity Monitor (then run nginx & have the cli app create a new nginx.pid file) or if you REALLY need to keep nginx running but want to run nginx -s reload - manually create a file in the /run path called nginx.pid and insert the PID of the currently running nginx processs (obtained via Activity Monitor).
To reload the custom config file use
nginx -s reload -c /etc/nginx/conf.d/<config file>.conf
This could simply mean that nginx is already stopped - not running at the moment.
First, confirm whether nginx is running, execute:
$ ps aux | grep nginx
i got the same error link you, i tried many way to fix it but it not working
after that i run the command line and it work well:
nginx -c /usr/local/etc/nginx/nginx.conf
the information i got from here
https://blog.csdn.net/wn1245343496/article/details/77974756
One way to stop or reload is through the below command,
For stop:
sudo /usr/local/nginx/sbin/nginx -s stop
Run reload only if the nginx is running:
sudo /usr/local/nginx/sbin/nginx -s reload
By doing like the above, you wont get nginx: [error] open() "/usr/local/var/run/nginx.pid" this issue

Monit + RVM + Thin on OSX / Linux

After trying for hours (and also trying God and Bluepill) I decided to ask my question here because I am completely clueless how to solve this issue.
I have a Rails app. I want to use Thin as my app server. I want to use Monit to monitor my Thin instances. I use RVM to manage my Ruby versions as my local user.
I have the following monit file set up that would assumably do what I want it to do, but doesn't:
check process thin-81
with pidfile /Users/Michael/Desktop/myapp/tmp/pids/thin.81.pid
start program = "/Users/Michael/.rvm/gems/ruby-1.9.2-p180/bin/thin start -c /Users/Michael/Desktop/myapp -e production -p 81 -d -P tmp/pids/thin.81.pid"
stop program = "/Users/Michael/.rvm/gems/ruby-1.9.2-p180/bin/thin stop -c /Users/Michael/Desktop/myapp -P tmp/pids/thin.81.pid"
if totalmem is greater than 150.0 MB for 2 cycles then restart
If I simply copy/paste the start program in to the command line (outside of Monit) it works. Same goes for the stop program to afterwards stop the Thin instance. Running it via Monit however, does not seem to work.
Running it in -v verbose mode yields the following:
monit: pidfile '/Users/Michael/Desktop/myapp/tmp/pids/thin.81.pid' does not exist
Which leads me to believe that Thin never initializes. Does Monit run as root or something? Cause if it does then it obviously won't have the correct gems installed since I'm using RVM and not the "system" Ruby. I am currently on OSX (but will deploy to Linux eventually) - does anyone know what the cause of this might be? And if Monit is run via root, how could I make it use RVM regardless? Or could I tell Monit to execute the start/stop programs as Michael:staff (I assume it would be on OSX?)
Any help is much appreciated!
monit clears out the environment and also doesn't run a shell for your command (let alone an interactive one). I find I have to do something like:
/usr/bin/bash -c 'export rvm_path=/home/foo/.rvm; . $rvm_path/scripts/rvm; cd my_ruby_app_path; $rvm_path/bin/rvm rvmrc load; ./my_ruby_app'
as the monit start command.
another option which I found in the RVM google group is as follows:
start program = "/bin/su - myuser -c '/path/to/myscript.rb start' "
su - user runs the user's shell as a login shell, so if the
user's shell is bash, it will cause ~/.bash_profile to be run so the
environment variables should be the same as just after that user
logged in.
We need the path for su, otherwise, monitrc would not able to find the su executable.
A better way would be to use an RVM wrapper to create a custom executable for thin. It will create the correct environment variables to use the right ruby and gems, and then launch thin. Read more about it using it with god here : https://rvm.io/integration/god/. It should work the same with monit
To create the wrapper:
rvm wrapper ruby#gemset bootup thin
Then change start program and stop program to use the executable you just created.

Resources