How do you know if memcached is doing anything? - django

I'm testing out using memcached to cache django views. How can I tell if memcached is actually caching anything from the Linux command line?

You could use the official perl script:
memcached-tool 127.0.0.1:11211 stats
Or just use telnet and the stats command e.g.:
# telnet localhost [memcacheport]
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 2239
STAT uptime 10228704
STAT time 1236714928
STAT version 1.2.3
STAT pointer_size 32
STAT rusage_user 2781.185813
STAT rusage_system 2187.764726
STAT curr_items 598669
STAT total_items 31363235
STAT bytes 37540884
STAT curr_connections 131
STAT total_connections 8666
STAT connection_structures 267
STAT cmd_get 27
STAT cmd_set 30694598
STAT get_hits 16
STAT get_misses 11
STAT evictions 0
STAT bytes_read 2346004016
STAT bytes_written 388732988
STAT limit_maxbytes 268435456
STAT threads 4
END

I know this question is old, but here is another useful approach for testing memcached with django:
As #Jacob mentioned, you can start memcached in very verbose mode (not as a daemon):
memcached -vv
To test your django cache config, you can use the low-level cache api.
First, start up the python interpreter and load your django project settings:
python manage.py shell
From the shell, you can use the low-level cache api to test your memcache server:
from django.core.cache import cache
cache.set('test', 'test value')
If your cache configuration is correct, you should see output in memcache similar to this:
<32 set :1:test 0 300 10
>32 STORED

Start memcache not as a daemon but normal, so just run memcached -vv for very verbose. You will see when get's and sets come in to the memcache server.

Simple way to test for memcache working was to sneak in a commented out timestamp on every page served up. If the timestamp stayed the same on multiple requests to a page, then the page was being cached by memcache.
In Django settings, I also setup the cache mechanism to use a file cache on the filesystem (really slow), but after hitting up the pages I could see that there were actual cache files being placed in the file path so I could confirm caching was active in Django.
I used both these steps to work out my caching problem. I actually did not have caching turned on correctly in Django. The newer method to activate caching is using the 'django.middleware.cache.CacheMiddleware' middleware (not the middleware with two middleware pieces that have to be the first/last middleware settings.)

From the command line, try the command below:
echo stats | nc 127.0.0.1 11211
If it doesn't return anything, memcache isn't running. Otherwise it should return a bunch of stats including uptime (and hit and miss counts)
The reference article is here,
https://www.percona.com/blog/2008/11/26/a-quick-way-to-get-memcached-status/
To see changes every 2 seconds:
watch "echo stats | nc 127.0.0.1 11211"

In Bash, you can check the statistics of memcache by this command:
exec 3<>/dev/tcp/localhost/11211; printf "stats\nquit\n" >&3; cat <&3
To flush the cache, use memflush command:
echo flush_all >/dev/tcp/localhost/11211
and check if the stats increased.
To dump all the cached objects, use memdump or memcdump command (part of memcached/libmemcached package):
memcdump --servers=localhost:11211
or:
memdump --servers=localhost:11211
If you're using PHP, to see whether is supported, check by: php -i | grep memcached.
Tracing
To check what memcached process is exactly processing, you can use network sniffers or debuggers (e.g. strace on Linux or dtrace/dtruss on Unix/OS X) for that. Check some examples below.
Strace
sudo strace -e read,write -fp $(pgrep memcached)
To format output in a better way, check: How to parse strace in shell into plain text?
Dtruss
Dtruss is a dtrace wrapper which is available on Unix systems. Run it as:
sudo dtruss -t read -fp $(pgrep memcached)
Tcpdump
sudo tcpdump -i lo0 -s1500 -w- -ln port 11211 | strings -10

Memcached can actually write to a logfile on its own, without having to resort to restarting it manually. The /etc/init.d/memcached init script (/usr/lib/systemd/system/memcached.service on EL7+; ugh) can call memcached with the options specified in /etc/memcached.conf (or /etc/sysconfig/memcached on EL5+). Among these options are verbosity and log file path.
In short, you just need to add (or uncomment) these two lines to that conf/sysconfig file...
-vv
logfile /path/to/log
...and restart the daemon with service memcached restart(EL3-7) or /etc/init.d/memcached restart(debuntus)
And then you can monitor this log in the traditional way, like tail -f /path/to/log, for example.

For extend Node's response, you can use socat UNIX-CONNECT:/var/run/memcached.sock STDIN to debug a unix socket.
Example:
$ socat UNIX-CONNECT:/var/run/memcached.sock STDIN
stats
STAT pid 931
STAT uptime 10
STAT time 1378574384
STAT version 1.4.13
STAT libevent 2.0.19-stable
STAT pointer_size 32
STAT rusage_user 0.000000
STAT rusage_system 0.015625
STAT curr_connections 1
STAT total_connections 2
STAT connection_structures 2

You can test memcached or any server by below script
lsof -i :11211 | grep 'LISTEN'>/dev/null 2>/dev/null;echo $?
if it returns 0 then the server is actually running or if 1 its not so if you want to know that the server is actually running on some port use the following script
lsof -i :11211 | grep 'LISTEN'>/dev/null 2>/dev/null;
if [ $? -eq 0]; then
echo "Your memcache server is running"
else
echo "No its not running"
fi

Can you use curl to fetch a page a few hundred times and time the results? You could also look at running a process on the server that simulates heavy CPU/disk load while doing this.

I wrote an expect script is-memcached-running that tests if memcached is running on a host/port combination (run as is-memcached-running localhost 11211):
#! /usr/bin/env expect
set timeout 1
set ip [lindex $argv 0]
set port [lindex $argv 1]
spawn telnet $ip $port
expect "Escape character is '^]'."
send stats\r
expect "END"
send quit\r
expect eof
If you run your system from a Makefile rule, you could make your startup depend on a make target that asserts it is up and running (or helps you get that state). It is verbose when the check fails to make it easy for us to debug failed ci runs, installs memcached when it's missing, and is brief and to the point otherwise:
#! /bin/bash
if [[ "$(type -P memcached)" ]]; then
echo 'memcached installed; checking if it is running'
memcached_debug=`mktemp memcache-check.XXXXX`
if is-memcached-running localhost 11211 >$memcached_debug 2>&1; then
echo 'Yep; memcached online'
else
cat $memcached_debug
echo
echo '****** Error: memcached is not running! ******'
if [[ "$OSTYPE" =~ ^darwin ]]; then
echo
echo 'Instructions to auto-spawn on login (or just start now) are shown'
echo 'at the end of a "brew install memcached" run (try now, if you did'
echo 'not do so already) or, if you did, after a "brew info memcached".'
echo
fi
exit 1
fi
rm -f $memcached_debug
else
echo memcached was not found on your system.
if [[ "$OSTYPE" =~ ^darwin ]]; then
brew install memcached
elif [[ "$OSTYPE" =~ ^linux ]]; then
sudo apt-get install memcached
else
exit 1
fi
fi

Following Aryashree post, this helped me to get an error if memcached not running locally:
import subprocess
port = 11211
res = subprocess.Popen(f"echo stats | nc 127.0.0.1 {port}",
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if res.stdout:
lines = res.stdout.read()
lineArr = lines.split('\r\n')
pidlineArr = lineArr[0].split(' ')
pid = pidlineArr[-1]
print(f"[MemCached] pid {pid} Running on port {port}")
else:
raise RuntimeError(f"No Memcached is present on port {port}")

I'm using Mezzanine and the only answer that worked for me was Jacobs answer. So stopping the daemon and running memcached -vv

If you're using RHEL or Centos 8
To get memcached log stuff to /var/log/messages (quick without rotation)
https://serverfault.com/questions/208538/how-to-specify-the-log-file-for-memcached-on-rhel-centos/1054741#1054741

Related

Django redis docker: port is already allocated [duplicate]

When I run docker-compose up in my Docker project it fails with the following message:
Error starting userland proxy: listen tcp 0.0.0.0:3000: bind: address already in use
netstat -pna | grep 3000
shows this:
tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN -
I've already tried docker-compose down, but it doesn't help.
In your case it was some other process that was using the port and as indicated in the comments, sudo netstat -pna | grep 3000 helped you in solving the problem.
While in other cases (I myself encountered it many times) it mostly is the same container running at some other instance. In that case docker ps was very helpful as often I left the same containers running in other directories and then tried running again at other places, where same container names were used.
How docker ps helped me:
docker rm -f $(docker ps -aq) is a short command which I use to remove all containers.
Edit: Added how docker ps helped me.
This helped me:
docker-compose down # Stop container on current dir if there is a docker-compose.yml
docker rm -fv $(docker ps -aq) # Remove all containers
sudo lsof -i -P -n | grep <port number> # List who's using the port
and then:
kill -9 <process id> (macOS) or sudo kill <process id> (Linux).
Source: comment by user Rub21.
I had the same problem. I fixed this by stopping the Apache2 service on my host.
You can kill the process listening on that port easily with one command below :
kill -9 $(lsof -t -i tcp:<port#>)
ex :
kill -9 $(lsof -t -i tcp:<port#>)
or for ubuntu:
sudo kill -9 `sudo lsof -t -i:8000`
Man page for lsof : https://man7.org/linux/man-pages/man8/lsof.8.html
-9 is for hard kill without checking any deps.
(Not related, but might be useful if its PORT 5000 mystery) - the culprit process is due to Mac OS monterery.
The port 5000 is commonly used to serve local development servers. When updating to the latest macOS operating system, I was unable the docker to bind to port 5000, because it was already in use. (You may find a message along the lines of Port 5000 already in use.)
By running lsof -i :5000, I found out the process using the port was named ControlCenter, which is a native macOS application. If this is happening to you, even if you use brute force (and kill) the application, it will restart itself. In my laptop, lsof -i :5000 returns that Control Center is being used by process id 433. I could do killall -p 433, but macOS keeps restarting the process.
The process running on this port turns out to be an AirPlay server. You can deactivate it in
System Preferences › Sharing, and unchecking AirPlay Receiver to release port 5000.
I had same problem,
docker-compose down --rmi all (in the same directory where you run docker-compose up)
helps
UPD: CAUTION - this will also delete the local docker images you've pulled (from comment)
For Linux/Unix:
Simple search for linux utility using following command
netstat -nlp | grep 8888
It'll show processing running at this port, then kill that process using PID (look for a PID in row) of that process.
kill PID
In some cases it is critical to perform a more in-depth debugging to the problem before stopping a container or killing a process.
Consider following the checklist below:
1) Check you current docker compose environment
Run docker-compose ps. If port is in use by another container, stop it with docker-compose stop <service-name-in-compose-file> or remove it by replacing stop with rm.
2) Check the containers running outside your current workspace
Run docker ps to see list of all containers running under your host.
If you find the port is in use by another container, you can stop it with docker stop <container-id>.
(*) Because you're not under the scope of the origin compose environment - it is a good practice first to use docker inspect to gather more information about the container that you're about to stop.
3) Check if port is used by other processes running on the host
For example if the port is 6379 run:
$ sudo netstat -ltnp | grep ':6379'
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 915/redis-server 12
tcp6 0 0 ::1:6379 :::* LISTEN 915/redis-server 12
(*) You can also use the lsof command which is mainly used to retrieve information about files that are opened by various processes (I suggest running netstat before that).
So, In case of the output above the PID is 915. Now you can run:
$ ps j 915
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 915 915 915 ? -1 Ssl 123 0:11 /usr/bin/redis-server 127.0.0.1:6379
And see the ID of the parent process (PPID) and the execution command.
You can also run: $ pstree -s <PID> to a visual display of the process and its related processes.
In our case we can see that the process probably is a daemon (PPID is 1) - In that case consider running: A) $ cat /proc/<PID>/status in order to get a more in-depth information about the process like the number of threads spawned by the process, its capabilities, etc'.
B) $ systemctl status <PID> in order to see the systemd unit that caused the creation of a specific process. If the service is not critical - you can stop and disable the service.
4) Restart Docker service
Run: sudo service docker restart.
5) You reached this point and..
Only if its not placing your system at risk - consider restarting the server.
In my case it was
Error starting userland proxy: listen tcp 0.0.0.0:9000: bind: address already in use
And all that I need is turn off debug listening in php storm
Most probably this is because you are already running a web server on your host OS, so it conflicts with the web server that Docker is attempting to start.
So try this one-liner before trying anything else:
sudo service apache2 stop; sudo service nginx stop; sudo nginx -s stop;
I had apache running on my ubuntu machine. I used this command to kill it!
sudo /etc/init.d/apache2 stop
I was getting the below error when i was trying to launch a new container -
listen tcp 0.0.0.0:8080: bind: address already in use.
To check which process is running on port 8080, run below command:
netstat -tulnp | grep 8080
i got the output below
[root#ip-112-x6x-2x-xxx.xxxxx.compute.internal (aws_main) ~]# netstat -tulnp | grep 8080 tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN **12749**/java [root#ip-112-x6x-2x-xxx.xxxxx.compute.internal (aws_main) ~]#
run
kill -9 12749
Then try to relaunch the container it should work
If redis server is started as a service, it will restart itself when you using kill -9 <process_id> or sudo kill -9 `sudo lsof -t -i:<port_number>` . In that case you will need to stop the redis service using following command.
sudo service redis-server stop
I upgraded my docker this afternoon and ran into the same problem. I tried restarting docker but no luck.
Finally, I had to restart my computer and it worked. Definitely a bug.
Check docker-compose.yml, it might be the case that the port is specified twice.
version: '3'
services:
registry:
image: mysql:5.7
ports:
- "3306:3306" <--- remove either this line or next
- "127.0.0.1:3306:3306"
Changing network_mode: "bridge" to "host" did it for me.
This with
version: '2.2'
services:
bind:
image: sameersbn/bind:latest
dns: 127.0.0.1
ports:
- 172.17.42.1:53:53/udp
- 172.17.42.1:10000:10000
volumes:
- "/srv/docker/bind:/data"
environment:
- 'ROOT_PASSWORD=secret'
network_mode: "host"
I ran into the same issue several times. Restarting docker seems to do the trick
A variation of #DmitrySandalov's answer: I had tomcat/java running on 8080, which needed to keep going. Looked at the docker-compose.yml file and altered the entry for 8080 to another of my choosing.
nginx:
build: nginx
ports:
#- '8080:80' <-- original entry
- '8880:80'
- '8443:443'
Worked perfectly. (The only wrinkle is the change will be wiped if I ever update the project, since it's coming from an external repo.)
At first, make sure which service you are running in your specific port. In your case, you are already using port number 3000.
netstat -aof | findstr :3000
now stop that process which is running on specific port
lsof -i tcp:3000
I resolve the issue by restarting Docker.
It makes more sense to change the port of the docker update instead of shutting down other services that use port 80.
Just a side note if you have the same issue and is with Windows:
In my case the process in my way is just grafana-server.exe. Because I first downloaded the binary version and double click the executable, and it now starts as a service by user SYSTEM which I cannot taskkill (no permission)
I have to go to "Service manager" of Windows and search for service "Grafana", and stop it. After that port 3000 is no longer occupied.
Hope that helps.
The one that was using the port 8888 was Jupiter and I had to change the configuration file of Jupiter notebook to run on another port.
to list who is using that specific port.
sudo lsof -i -P -n | grep 9
You can specify the port you want Jupyter to run uncommenting/editing the following line in ~/.jupyter/jupyter_notebook_config.py:
c.NotebookApp.port = 9999
In case you don't have a jupyter_notebook_config.py try running jupyter notebook --generate-config. See this for further details on Jupyter configuration.
Before it was running on :docker run -d --name oracle -p 1521:1521 -p 5500:5500 qa/oracle
I just changed the port to docker run -d --name oracle -p 1522:1522 -p 5500:5500 qa/oracle
it worked fine for me !
On my machine a PID was not being shown from this command netstat -tulpn for the in-use port (8080), so i could not kill it, killing the containers and restarting the computer did not work. So service docker restart command restarted docker for me (ubuntu) and the port was no longer in use and i am a happy chap and off to lunch.
maybe it is too rude, but works for me. restart docker service itself
sudo service docker restart
hope it works for you also!
I have run the container with another port, like... 8082 :-)
I came across this problem. My simple solution is to remove the mongodb from the system
Commands to remove mongodb in Ubuntu:
sudo apt-get purge mongodb mongodb-clients mongodb-server mongodb-dev
sudo apt-get purge mongodb-10gen
sudo apt-get autoremove
Let me add one more case, because I had the same error and none of the solutions listed so far works:
serv1:
...
networks:
privnet:
ipv4_address: 10.10.100.2
...
serv2:
...
# no IP assignment, no dependencies
networks:
privnet:
ipam:
driver: default
config:
- subnet: 10.10.100.0/24
depending on the init order, serv2 may get assigned the IP 10.10.100.2 before serv1 is started, so I just assign IPs manually for all containers to avoid the error. Maybe there are other more elegant ways.
I have the same problem and by stopping docker container it was resolved.
sudo docker container stop <container-name>
i solved with this sudo service redis-server stop

Something is flusing iptables after some hours of fail2ban reload

Several days ago I asked this question Confuse about fail2ban behavior with firewallD in Centos 7
It is a large text with several comments.
It seems something starts flushing iptables after some hours of fail2ban restart I don't get what it is.
A couple of months ago I moved a few Virtual Hosts from a dedicated server I used for more than 10 years to a Contabo VPS.
All goes fine but fail2ban jail. Prisoners escape. :)
My move was from Centos 6 to Centos 7 Webmin/Virtualmin LAMP fail2ban; leaving /etc/sysconfig/iptables, now using firewalld.
As said, after some hours of fail2ban restart, and after some successfully banned IPs, as #sebres suggested, something is flushing iptables because of the symptom "after effects" like
2019-12-05 16:55:20,856 fail2ban.action [1514]: ERROR iptables -w -n -L INPUT | grep -q 'f2b-proftpd[ \t]' -- stdout: ''
and "already banned" notices.
None of the changes I tried in default configurations changed that.
At the end I deleted the Webmin module to manage fail2ban and reinstalled the service.
Renamed /etc/fail2ban to keep backup configurations.
rpm -qa | grep -i fail2ban
then
yum remove fail2ban-server
yum remove fail2ban-firewalld
yum install fail2ban-firewalld (also installs -server)
yum install fail2ban-systemd
then copied old jail.local to new /etc/fail2ban directory
[DEFAULT]
banaction = iptables-multiport
banaction_allports = iptables-allports
[sshd]
enabled = true
port = ssh
maxretry = 4
bantime = 7200
[ssh-ddos]
enabled = true
port = ssh,sftp
filter = sshd-ddos
[webmin-auth]
enabled = true
port = 10000
[proftpd]
enabled = true
bantime = -1
[postfix]
enabled = true
bantime = -1
[dovecot]
enabled = true
bantime = -1
[postfix-sasl]
enabled = true
bantime = -1
I also checked cron jobs to see if something can be flushing iptables in any way.
At this time I have running, periodically, a script to manually reject those "already banned" IPs once.
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='xxx.xxx.xxx.xxx' reject"
So my question is how to know what is flusing iptables.
UPADATE 1
After update to stable V 0.10 fail2ban release it seemed problems gone but after 5 days they started again.
Previously, after v0.9 restart, problems started after few hours.
UPADATE 2
Running fail2ban-client -d I got "Found no accessible config files for 'filter.d/sshd-ddos'". That's because I kept the old ssh-ddos config in jail.conf.
So, a subquestion is if I'm right simply making this change (at least no errors in fail2ban-client -d
#filter = sshd-ddos
filter = sshd
mode = agressive (as suggested by #sebres)
Here's the output of fail2ban-client -d
"No, the after effect is there because something is flushing rules, not vice versa"
I understand that, I'm not that fluent in English speaking, I meant that that was a symptom that something happens so the effect.
"So which banning action do you use really?"
Sorry my poor knowledge on this matter. Is that what is included in [Default] part of jail.local?
"(for example can you exclude some service implemented by Contabo installed or integrated in your VPS, that doing that?"
I asked them some time ago but their answer was "...we are providing our customers with the basic installations..." nothing that technical. They have several VPS services and I don't see other people complaining about that.
UPDATE 3
The first jail.local (from fresh Webmin/Virtualmin install) actions were
action = firewallcmd-ipset[]
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
I changed by
banaction = iptables-multiport
banaction_allports = iptables-allports
some time ago.
Now I went back with firewallcmd-ipset as [DEFAULT] and this is the fail2ban-client -d output.
I'll check fail2ban.log. .... After few hours, problems again.
About firewallD Webmin has a section with defined zones/rules and tools to manage them instead of having to write commands in shell. Nothing more.
I cannot imagine fail2ban blame here, but to exclude it (or some action of fail2ban is broken on your side), we should take a look into your configuration...
So provide your whole (unmodified) configuration dump:
fail2ban-client -d
or at least dump of all actions of all jails:
fail2ban-client -d | grep 'action'
now using firewalld
I see pretty sure iptables in your config and the log excerpt (error message).
So which banning action do you use really?
something is flushing iptables because of "after effects" like ...
No, the after effect is there because something is flushing rules, not vice versa.
This can be for example some "firewall" script which you apply to configure iptables (ports, default reject rules, etc), restart of some service due to dependency (restarting or reloading iptables), some script mistakenly implementing knocking, and many others.
I don't think it'd be simple to find it, if you don't have it under your control (for example can you exclude some service implemented by Contabo installed or integrated in your VPS, that doing that?).
UPDATE 1:
I don't see any error in your excerpt... to remove f2b-proftpd (or flush input chain) it should contain:
either <iptables> -D INPUT ... -j f2b-proftpd
or even <iptables> -F INPUT somewhere in actions parameters, excepting actionstop (which is intended stop by shutdown or restart case only).
But it is only available in actionstop as expected:
all entries containing removal from INPUT chain (actionstop only):
<iptables> -D INPUT -p tcp -m multiport --dports ssh -j f2b-sshd
<iptables> -D INPUT -p tcp -m multiport --dports 10000 -j f2b-webmin-auth
<iptables> -D INPUT -p tcp -m multiport --dports ftp,ftp-data,ftps,ftps-data -j f2b-proftpd
<iptables> -D INPUT -p tcp -m multiport --dports smtp,465,submission -j f2b-postfix
<iptables> -D INPUT -p tcp -m multiport --dports pop3,pop3s,imap,imaps,submission,465,sieve -j f2b-dovecot
<iptables> -D INPUT -p tcp -m multiport --dports smtp,465,submission,imap,imaps,pop3,pop3s -j f2b-postfix-sasl
<iptables> -D INPUT -p tcp -m multiport --dports ssh,sftp -j f2b-ssh-ddos
Thus we could exclude the blame of fail2ban.
Just you said "now using firewalld" - where? In your config dump I see iptables-multiport only:
['set', 'sshd', 'addaction', 'iptables-multiport']
['set', 'webmin-auth', 'addaction', 'iptables-multiport']
['set', 'proftpd', 'addaction', 'iptables-multiport']
['set', 'postfix', 'addaction', 'iptables-multiport']
['set', 'dovecot', 'addaction', 'iptables-multiport']
['set', 'postfix-sasl', 'addaction', 'iptables-multiport']
['set', 'ssh-ddos', 'addaction', 'iptables-multiport'],
So for example if firewald would rewrite INPUT chain of iptables (removes fail2ban entries), you would catch exactly this issue.
Thus better find out which major netfilter your system use and use it as banaction (or avoid rewriting of fail2ban rules e. g. by adding it to fail2ban dependencies, etc).

Best way to find out when old nginx configuration dropped all requests

I'm writing a 0dt deploy script for django.
When a deploy is made, it creates a new django server with the most recent code version, writes a new nginx config pointing to the right socket and reload nginx.
How do I find out when the old nginx workers replied all connections so I can drop the old django server?
Is looking at the workers pid the best option? I can't use nginx status url because the old config stops receiving connections.
Additionaly, there's another problem. Django is my backend, nginx is also proxying to a node server to serve the client. Is it possible to look at the active connections of a single upstream? Otherwise I will have to wait all connections to finish on the frontend too.
Well, in case anyone comes looking for it, I ended up with this solution:
[...]
# Run API
echo ":: Starting new server"
pm2 start ./server.sh --name api-$PRJ > /dev/null
# Copy nginx config
#echo ":: Swap nginx config"
rm ~/nginx/api.atados.com.br.*
cp ~/deploy/api/nginx.conf ~/nginx/api.atados.com.br.$PRJ.conf
perl -pi -e 's/{PRJ}/$PRJ/g' ~/nginx/api.atados.com.br.$PRJ.conf
# Grab workers pid
workers=`ps -aux | grep "nginx: worker" | sed "$ d" | awk '{print $2}'`
# Reload nginx
echo ":: Reloading nginx and waiting for old connections to drop."
sudo service nginx reload > /dev/null
# Wait for workers to die
for job in $workers
do
while [ -e /proc/$job ]
do
sleep 1
done
done
# Close old server
pm2 list | grep api | awk '{print $2}' | grep -v $PRJ | xargs pm2 delete > /dev/null
[...]

How to stop gunicorn properly

I'm starting gunicorn with the Django command python manage.py run_gunicorn. How can I stop gunicorn properly?
Note: I have a semi-automated server deployment with fabric. Thus using something like ps aux | grep gunicorn to kill the process manually by pid is not an option.
To see the processes is ps ax|grep gunicorn and to stop gunicorn_django is pkill gunicorn.
One option would be to use Supervisor to manage Gunicorn.
Then again i don't see why you can't kill the process via Fabric.
Assuming you let Gunicorn write a pid file you could easily read that file in a Fabric command.
Something like this should work:
run("kill `cat /path/to/your/file/gunicorn.pid`")
pkill gunicorn
or
pkill -P1 gunicorn
should kill all running gunicorn processes
pkill gunicorn stops all gunicorn daemons. So if you are running multiple instances of gunicorn with different ports, try this shell script.
#!/bin/bash
Port=5000
pid=`ps ax | grep gunicorn | grep $Port | awk '{split($0,a," "); print a[1]}' | head -n 1`
if [ -z "$pid" ]; then
echo "no gunicorn deamon on port $Port"
else
kill $pid
echo "killed gunicorn deamon on port $Port"
fi
ps ax | grep gunicorn | grep $Port shows the daemons with specific port.
Here is the command which worked for me :
pkill -f gunicorn
It will kill any process with the name gunicorn
Start:
gunicorn --pid PID_FILE APP:app
Stop:
kill $(cat PID_FILE)
The --pid flag of gunicorn requires a single parameter: a file where the process id will be stored. This file is also automatically deleted when the service is stopped.
I have used PID_FILE for simplicity but you should use something like /tmp/MY_APP_PID as file name.
If the PID file exists it means the service is running. If it is not there, the service is not running. To stop the service just kill it as mentioned.
You could also want to include the --daemon flag in order to detach the process from the current shell.
To start the service which is running on gunicorn
sudo systemctl enable myproject
sudo systemctl start myproject
or
sudo systemctl restart myproject
But to stop the service running on gunicorn
sudo systemctl stop myproject
to know more about python application hosting using gunicorn please refer here
kill -9 `ps -eo pid,command | grep 'gunicorn.*${moduleName:appName}' | grep -v grep | sort | head -1 | awk '{print $1}'`
ps -eo pid,command will only fetch process id, command and args out
grep -v grep to get rid of output like 'grep --color=auto xxx'
sort | head -1 to do ascending sort and get first line
awk '{print $1}' to get pid back
One more thing you may need to pay attention to: Where gunicorn is installed and which one you're using?
Ubuntu 16 has gunicorn installed by default, the executable is gunicorn3 and located on /usr/bin/gunicorn3, and if you installed it by pip, it's located on /usr/local/bin/gunicorn. You would need to use which gunicorn and gunicorn -v to find out.
In your terminal, do:
ps ax|grep gunicorn
Then to kill the Gunicorn process, just do that:
kill -9 <gunicorn pid number>
In my case I dealt with many processes
For example: kill -9 398 399 4225 4772
The above solutions does not remove pid file when the process is killed.
cat <pid-file> | xargs kill -2
This solution reads pid file and send interrupt signal. This closes gunicorn properly and pid file is also removed.
PID file can be generated by
gunicorn --pid PID-FILE
or by adding the following in config file
pidfile = "pid_file"
If we run:
pkill gunicorn
We stop all gunicorn services, in this case to start gunicorn we only need to stop the parent process associated with the service that attends the port where gunicorn will be executed.
The following script searches for said process (pid), if it exists it kills this process:
#!/bin/bash
# ---------------------
stop_unicorn_on_port() {
pid=$(lsof -w -t -i "TCP:${1}" | head -1)
if [ -z "${pid}" ]; then
echo "🦄 no service deamon on port ${1}"
else
kill -9 "${pid}"
echo "🦄 killed service deamon(${pid}) on port ${1}"
fi
}
# Example/Testing
stop_unicorn_on_port 5000
stop_unicorn_on_port 5001
stop_unicorn_on_port 5002
more info check: man lsoft
-t specifies that lsof should produce terse output with process identifiers only and no header - e.g., so
that the output may be piped to kill(1). -t selects the -w option.
-iselects the listing of files any of whose Internet address matches the address specified in i. If no
address is specified, this option selects the listing of all Internet and x.25 (HP-UX) network files...
Here are some sample addresses:
-i6 - IPv6 only
TCP:25 - TCP and port 25
#1.2.3.4 - Internet IPv4 host address 1.2.3.4
I built upon #David's recommendation to use --pid (PID_FILE) to fix the problem I faced because killing the parent pid didn't kill worker processes.
import os
import sys
import psutil
def stop_pid(pid):
if sys.platform == 'win32':
p = psutil.Process(pid)
p.terminate() # or p.kill()
else:
os.system('kill -9 {0}'.format(pid))
def get_child_pids(ppid):
pid_list = []
for process in psutil.process_iter():
_ppid = process.ppid()
if _ppid == ppid:
_pid = process.pid
pid_list.append(_pid)
return pid_list
def send_kill_cmd(ppid, cpids):
stop_pid(ppid) # Killing the parent proc first
for pid in cpids:
stop_pid(pid)
if __name__ == '__main__':
parent_pid = int(sys.argv[1])
child_pids = get_child_pids(parent_pid)
send_kill_cmd(parent_pid, child_pids)
Then finally excecuted above python script with below commands
#!/bin/bash
FILE_NAME=PID_FILE
if [ -f "$FILE_NAME" ]; then
pypy stop_gunicorn.py "$(cat PID_FILE)"
echo "killed - $(cat PID_FILE) and it's child processes."
sleep 2
fi
echo 'Starting gunicorn'
nohup gunicorn --workers 1 --bind 0.0.0.0:5050 app:app --thread 50 --worker-class eventlet --reload --pid PID_FILE > nohup_outs/nohup_process.out &

How to 'clear' the port when restarting django runserver

Often, when restarting Django runserver, if I use the same port number, I get a 'port is already in use' message. Subsequently, I need to increment the port number each time to avoid this.
It's not the case on all servers, however, so I'm wondering how I might achieve this on the current system that I'm working on?
BTW, the platform is Ubuntu 8.10
I found this information (originally from Kristinn Örn Sigurðsson) to solve my problem:
To kill it with -9 you will have to list all running manage.py processes, for instance:
ps aux | grep -i manage
You'll get an output similar to this if you've started on many ports:
14770 8264 0.0 1.9 546948 40904 ? S Sep19 0:00 /usr/local/bin/python manage.py runserver 0.0.0.0:8006
14770 15215 0.0 2.7 536708 56420 ? S Sep13 0:00 /usr/local/bin/python manage.py runserver 0.0.0.0:8001
14770 30144 0.0 2.1 612488 44912 ? S Sep18 0:00 /usr/local/bin/python manage.py runserver 0.0.0.0:8000
14770 30282 0.0 1.9 678024 40104 ? S Sep18 0:00 /usr/local/bin/python manage.py runserver 0.0.0.0:8002
14770 30592 0.0 2.1 678024 45008 ? S Sep18 0:00 /usr/local/bin/python manage.py runserver 0.0.0.0:8003
14770 30743 0.0 2.1 678024 45044 ? S Sep18 0:00 /usr/local/bin/python manage.py runserver 0.0.0.0:8004
Then you'll have to select the pid (which is the second number on the left) for the right manage.py process (python manage.py runserver... etc) and do:
kill -9 pid
For the above example, if you wanted to free up port 8000, you'd do:
kill -9 30144
You're getting that message because the server is already running (possibly in the background). Make sure to kill the process (bring it to the foreground and press ctrl-c) to stop the process.
If the ps aux command (as per Meilo's answer) doesn't list the process that you wanted to kill but shows the port active in netstat -np | grep 8004 network activity, try this command (worked on Ubuntu).
sudo fuser -k 8004/tcp
where as, 8004 is the port number that you want to close.
This should kill all the processes associated with port 8004.
No, he's not an idiot guys. Same thing happens to me. Apparently it's a bug with the python UUID process with continues running long after the django server is shutdown which ties the port up.
fuser -k 8000/tcp
Run in terminal it works in ubutu. 8000 is the port.
This error is due to the server already running.
Background
I am answering on a more general level not specific to Django like the original question asks. So that those that land here from Google can easily fix the problem.
Solution
When you need to clear a port, all you need to do is these two steps
In the terminal run fg
Press Control-C (if on a mac)
Explanation
fg brings the process to the foreground. Then Control-C stops the server.
Example
I was actually having this issue with my port 8000 when running an angular app. I was getting an error when I ran npm start
So I ran fg, then I stopped the server with Control-C
Then I was able to successfully run the server
Type fg in the terminal to bring up the background task to the foreground.
Press Ctrl+C to close/stop the running server.
I use pkill -If 'manage.py' (-I means interactive, -f matches more than just the process name). See How to kill all processes with a given partial name? for more info on pkill.
sudo lsof -t -i tcp:8000 | xargs kill -9
If you want to free 8000 port than just copy command and paste in your cmd it will ask for sudo password. And then you are good to go.
If the port number that you are trying is 8001, then use this command
sudo fuser -k 8001/tcp
You do not want to simply increment the port number when restarting a Django server. This will result in having multiple instances of the Django server running simultaneously. A better solution is to kill the current instance and start a new instance.
To do this, you have multiple options. The easiest is
Python2: $ killall -9 python
Python3: $ killall -9 python3
If for some reason, this doesn't work, you can do
$ kill <pid> where <pid> is the process id found from a simple $ ps aux | grep python command.
netstat -tulpn |grep 8000|awk '{print $7}'|cut -d/ -f 1|xargs kill
Repost from https://stackoverflow.com/a/27138521/1467342:
You can use this script in place of ./manage.py runserver. I put it in scripts/runserver.sh.
#!/bin/bash
pid=$(ps aux | grep "./manage.py runserver" | grep -v grep | head -1 | xargs | cut -f2 -d" ")
if [[ -n "$pid" ]]; then
kill $pid
fi
fuser -k 8000/tcp
./manage.py runserver
Like mipadi said, you should be terminating the server (ctrl+c) and returning to the command prompt before calling manage.py runserver again.
The only thing that could be disrupting this would be if you've somehow managed to make runserver act as a daemon. If this is the case, I'm guessing you're using the Django test server as the actual web server, which you should NOT do. The Django test server is single threaded, slow and fragile, suitable only for local development.
In Leopard, I bring on the Activity Monitor and kill python. Solved.
Happened so often that I wrote an alias to kill the process with python in the name (careful if you have other such processes). Now I just run (no Ubuntu)
kill $(ps | grep "python" | awk "{print $1}")
You can even add python manage.py runserver ... to the same alias so you can restart with two keystrokes.
You must have been doing control + z .. Instead do control + c that will kill the server session... Cheers!!!
Add the following library in manage.py
import os
import subprocess
import re
Now add the following python code after if __name__ == "__main__":
ports = ['8000']
popen = subprocess.Popen(['netstat', '-lpn'],
shell=False,
stdout=subprocess.PIPE)
(data, err) = popen.communicate()
pattern = "^tcp.*((?:{0})).* (?P<pid>[0-9]*)/.*$"
pattern = pattern.format(')|(?:'.join(ports))
prog = re.compile(pattern)
for line in data.split('\n'):
match = re.match(prog, line)
if match:
pid = match.group('pid')
subprocess.Popen(['kill', '-9', pid])
This will first find the process id of port 8000 , will kill it and then restart your project. Now each time you don't need to kill the pid manually.
netstat -ntlp
See my complete answer here. https://stackoverflow.com/a/34824239/5215825