How to start Unicorn with systemctl and systemd - amazon-ec2

I would like to start Unicorn with systemctl on the amazon-linux-2, but the Unicorn doesn't start.
I've wrote a /etc/systemd/system/unicorn.service file.
[Unit]
Description=The unicorn process
[Service]
User=myname
WorkingDirectory=/var/www/rails/myapp
SyslogIdentifier=unicorn
Type=simple
ExecStart=/bin/bash -l -c 'bundle exec unicorn_rails -c /var/www/rails/myapp/config/unicorn.conf.rb -E production -D'
[Install]
WantedBy=multi-user.target
Here are the commands I used to start the service
sudo systemctl daemon-reload
sudo systemctl start unicorn.service
I can't find any process about unicorn with command ps -ef | grep unicorn | grep -v grep.
Here I check the status:
$ sudo systemctl status unicorn -l
● unicorn.service - The unicorn process
Loaded: loaded (/etc/systemd/system/unicorn.service; disabled; vendor preset: disabled)
Active: inactive (dead)
xxx.compute.internal systemd[1]: Started The unicorn process.
xxx.compute.internal systemd[1]: Starting The unicorn process...
Here is unicorn.log. (there aren't any error log)
I, [2020-11-25T20:00:24.564840 #6604] INFO -- : Refreshing Gem list
I, [2020-11-25T20:00:25.278814 #6604] INFO -- : unlinking existing socket=/var/www/rails/myapp/tmp/sockets/.unicorn.sock
I, [2020-11-25T20:00:25.279020 #6604] INFO -- : listening on addr=/var/www/rails/myapp/tmp/sockets/.unicorn.sock fd=9
I, [2020-11-25T20:00:25.299977 #6604] INFO -- : master process ready
I, [2020-11-25T20:00:25.406567 #6604] INFO -- : reaped #<Process::Status: pid 6607 exit 0> worker=0
I, [2020-11-25T20:00:25.406659 #6604] INFO -- : reaped #<Process::Status: pid 6608 exit 0> worker=1
I, [2020-11-25T20:00:25.406760 #6604] INFO -- : master complete
Why the unicorn doesn't start ?

Change Type=simple to Type=forking.

Related

Logrotate postrotate and docker exec strange behaviour

I'm trying to configure logrotate with docker container. I'm running httpd as background process in docker container, and after logrotate I need to reload it to use new log files. I don't want to restart the container because of possible downtime. Sending SIGHUP with docker kill --signal=HUP <container> is not working, as my entrypoint is bash script which does not handle signals. I tried to do it like this in logrotate config:
...
sharedscripts
postrotate
service httpd reload > /dev/null 2>/dev/null || true
docker exec some-container kill -HUP $(ps -e | awk '{print $1}')>>/tmp/exec-out.log 2>>/tmp/exec-out.log || true
endscript
but I got
kill: sending signal to 30 failed: No such process
kill: sending signal to 31 failed: No such process
kill: sending signal to 32 failed: No such process
kill: sending signal to 33 failed: No such process
kill: sending signal to 34 failed: No such process
kill: sending signal to 35 failed: No such process
kill: sending signal to 36 failed: No such process
kill: sending signal to 37 failed: No such process
kill: sending signal to 38 failed: No such process
I'm quite new to docker and linux and I don't really understand why docker gets process ids that do not exist.
EDIT: I also would not like to change the bash script to trap SIGHUP if possible, but instead solve the problem in logrotate config.
I believe the $(ps -e | awk '{print $1}')>>/tmp/exec-out.log 2>>/tmp/exec-out.log || true is being run in the context of the host not the docker and so gets the wrong pid as you can see.
If you ran the docker container with pid=host the pids will work.
Alternatively you can get the pid like so:
docker inspect --format {{.State.Pid}} <container>
But you don't actually need the pid, you can send a signal yourself using docker kill like so:
docker kill --signal=HUP some-container

systemd and StandardInput. taking control of tty

I have a systemd unit script which looks something like this
cat /usr/lib/systemd/system/hello.service
[Unit]
Description=Simple Hello World service
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=/root/hello.env
ExecStart=/bin/gdb /root/hello
StandardInput=tty-force
StandardOutput=inherit
TTYPath=/dev/pts/0
TTYReset=yes
TimeoutStartSec=infinty
[Install]
WantedBy=multi-user.target
The whole point is, i want to start the service with gdb on start up.[Since the process involves lot of environmental variables i cannot use the gdb directly on the process.]
systemctl start hello (which is actually working).
But once i exit out of gdb tty is completely messed up.None of the control key work, ^Z, ^C.
This are the observation till now.
As describer by systemd man pages with "StandardInput=tty-force", will actually force the executing process to take control of tty.
Before i launch the process
# tty
/dev/pts/0
# ps -aef | grep bash
root 2805 2803 0 10:42 pts/0 00:00:00 -bash
root 2860 2805 0 10:45 pts/0 00:00:00 grep --color=auto bash
After i launch
# tty
/dev/pts/0
# ps -aef | grep bash
root 2805 2803 0 10:42 ? 00:00:00 -bash
root 2884 2805 0 10:47 ? 00:00:00 grep --color=auto bash
Tried reset the terminal, still doesn't work.
subsequent systemctl command dsplay the below error
systemctl stop hello
Error creating textual authentication agent: Error opening current controlling terminal for the process (`/dev/tty'): No such device or address (polkit-error-quark, 0)
So the question is is there a way to reset the tty back to bash ?

Monit fails to start process

I've written a scrip that works fine to start and stop a server.
#!/bin/bash
PID_FILE='/var/run/rserve.pid'
start() {
touch $PID_FILE
eval "/usr/bin/R CMD Rserve"
PID=$(ps aux | grep Rserve | grep -v grep | awk '{print $2}')
echo "Starting Rserve with PID $PID"
echo $PID > $PID_FILE
}
stop () {
pkill Rserve
rm $PID_FILE
echo "Stopping Rserve"
}
case $1 in
start)
start
;;
stop)
stop
;;
*)
echo "usage: rserve {start|stop}" ;;
esac
exit 0
If I start it by running
rserve start
and then start monit it will correctly capture the PID and the server:
The Monit daemon 5.3.2 uptime: 0m
Remote Host 'localhost'
status Online with all services
monitoring status Monitored
port response time 0.000s to localhost:6311 [DEFAULT via TCP]
data collected Mon, 13 May 2013 20:03:50
System 'system_gauss'
status Running
monitoring status Monitored
load average [0.37] [0.29] [0.25]
cpu 0.0%us 0.2%sy 0.0%wa
memory usage 524044 kB [25.6%]
swap usage 4848 kB [0.1%]
data collected Mon, 13 May 2013 20:03:50
If I stop it, it will properly kill the process and unmonitor it. However if I start it again, it won't start the server again:
ps ax | grep Rserve | grep -vc grep
1
monit stop localhost
ps ax | grep Rserve | grep -vc grep
0
monit start localhost
[UTC May 13 20:07:24] info : 'localhost' start on user request
[UTC May 13 20:07:24] info : monit daemon at 4370 awakened
[UTC May 13 20:07:24] info : Awakened by User defined signal 1
[UTC May 13 20:07:24] info : 'localhost' start: /usr/bin/rserve
[UTC May 13 20:07:24] info : 'localhost' start action done
[UTC May 13 20:07:34] error : 'localhost' failed, cannot open a connection to INET[localhost:6311] via TCP
Here is the monitrc:
check host localhost with address 127.0.0.1
start = "/usr/bin/rserve start"
stop = "/usr/bin/rserve stop"
if failed host localhost port 6311 type tcp with timeout 15 seconds for 5 cycles
then restart
I had problem start or stop process via shell too.
One solution might be add "/bin/bash" in the config like this:
start program = "/bin/bash /urs/bin/rserv start"
stop program = "/bin/bash /urs/bin/rserv stop"
It worked for me.
monit is a silent killer. It does not tell you anything. Here are things I would check which monit won't help you identify
Check permissions of all the files you are reading / writing. If you are redirecting output to a file, make sure that file is writable by uid and gid you are using to execute the program
Again check exec permission on the program you are trying to run
Specify full path to any program you are trying to execute ( not strictly necessary, but you don't have to worry about path not being set if you always specify full path )
Make sure you can run the program outside of monit without any error before trying to investigate why monit is not starting.
If the Monit log is displaying
failed to start (exit status -1) -- no output
Then it may be that you're trying to run a script without any of the Bash infrastructure. You can run such a command by wrapping it in /bin/bash -c, like so:
check process my-process
matching "my-process-name"
start program = "/bin/bash -c '/etc/init.d/my-init-script'"
When monit starts it checks for its own pidfile and checks if the process with
matching PID is running already - if it does, then it just wakes up this
process.
in your case, check if this pid is being used by some other process:
ps -ef |grep 4370
if yes, then you need to remove the below file(usually under /run directory) and start monit again:
monit.pid
For me, the issue was that the stop command was not being run, even though I specifically specified "then restart" on the configuration.
The solution was just to change:
start program = "/etc/init.d/.... restart"

Having a IO.popen command be killed when the caller process is killed

I have a Ruby script that starts a subprocess. I want them to be killed when the overall process is killed.
IO.popen('testacular start unit.conf.js', 'w')
Run my script:
user.name:/my/repo [git: my-branch] $ ruby my-script.rb
Output from testacular:
user.name:/my/repo [git: my-branch] $ info: Testacular server started at http://localhost:8000/
info (launcher): Starting browser PhantomJS
info (PhantomJS 1.7): Connected on socket id uVAO41Q2niyLA8AqbZ8w
PhantomJS 1.7: Executed 44 of 44 SUCCESS (0.213 secs / 0.115 secs)
Hit Control-C to kill the process. Check the running processes:
user.name:/my/repo [git: my-branch] $ ps
PID TTY TIME CMD
# ...
39639 ttys019 0:01.28 node /usr/local/bin/testacular start unit.conf.js
39649 ttys019 0:00.09 node /usr/local/bin/phantomjs /var/folders/2p/dklw3xys2n3f4hqmx73zvz6w0000gp/T/testacular-61981618/capture.js
39650 ttys019 0:00.82 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs /var/folders/2p/dklw3xys2n3f4hqmx73zvz6w0000gp/T/testacular-61981618/capture.js
We can see that the testacular process is still running.
Kill it manually and see the typical testacular shutdown output:
user.name:/my/repo [git: my-branch] $ kill 39639
info: Disconnecting all browsers
error (launcher): Cannot start PhantomJS
user.name:/my/repo [git: my-branch] $
Is there a way to make the IO.popen call such that I don't have to manually kill testacular later?
Yes, you just need to install a signal handler in your main process to trap Ctrl-C (SIGINT) and then send that signal to the child process.
This example should explain things:
# Start child and save its pid
io = IO.popen("sleep 600")
pid = io.pid
# Print the output of the ps command (just for demonstration)
puts "Checking #{pid} ..."
system("ps #{pid}")
puts "Installing signal handler..."
Signal.trap("INT") {
# Ctrl-C was pressed...
puts "Caught interrupt - killing child..."
# Kill child process...
Process.kill("INT", pid)
  # This prevents the process from becoming defunct
io.close
# Just for demonstration purposes - check that it died
puts "Checking #{pid} ..."
system("ps #{pid}")
# Forward the INT signal back to the parent
# ...or you could just call "exit" here too.
puts "Forwarding signal to myself..."
Signal.trap("INT", "DEFAULT")
Process.kill("INT", 0)
}
# Make the parent "do some stuff"...
puts "Sleeping parent..."
sleep 600
Output:
> ruby popen_test.rb
Checking 2474 ...
PID TTY STAT TIME COMMAND
2474 pts/0 S+ 0:00 sleep 600
Installing signal handler...
Sleeping parent...
# Press Ctrl-C ...
Caught interrupt - killing child...
Checking 2474 ...
PID TTY STAT TIME COMMAND
Forwarding signal to myself...
kill.rb:20: Interrupt
from kill.rb:24:in `call'
from kill.rb:24:in `sleep'
from kill.rb:24
Note that the above approach does not work when the signal is a SIGKILL. In order to fix this, you could implement a pipe-based approach as shown in: https://github.com/vaneyckt/Adeona/blob/master/lib/adeona.rb

How to make daemon --stop blocking until underlying process will die?

I have a java process daemonized using daemon command (RHEL 6.2). I'm using following line to start the process and the line below to stop it:
daemon --command "/opt/my-service" --respawn --name=my-service --verbose
daemon --stop --name=my-service --verbose
Things work until I'll try to restart my process using stop/start approach:
daemon --stop --name=my-service --verbose
daemon --command "/opt/my-service" --respawn --name=my-service --verbose
It the process is running before the above command is executed, then existing process will be stopped but then new one will not be created. Instead, following line will be logged to the /var/log/messages:
Oct 27 07:59:46 myhostname my-service: my-service: fatal: failed to become a daemon: Resource temporarily unavailable
which as far as I understand means that we tried to acquire lock on the pid file but another process was holding the lock on it. Or in the other words: the original process was still running.
What is interesting it can not be reproduced by i.e. following command:
daemon --command "sleep 30s" --respawn --name=sleeper --verbose
daemon --stop --name=sleeper --verbose
daemon --command "sleep 30s" --respawn --name=sleeper --verbose
then there must be something in my process which causes/exploits asynchronous nature of --stop.
How can I make --stop blocking?
This might help:
while true; do
daemon --name=my-service --running --verbose | grep not
[ $? -eq 0 ] && exit
sleep 1
done
Description as p-code:
forever {
check if daemon --name=my-service --running --verbose returns some thing containing the word not
if yes, exit
otherwise sleep a second
}

Resources