Running Concurrent Bash Scripts and TasksMax Settings
For a long time, I had an Expect script to login network devices, fetch information and put the output together as a Web page. Think of it as a script checking router version, memory etc. It took about 30 seconds to finish checking a single target and would take hours to finish scanning several subnets.
Finally I think it is time to parallel these tasks so the whole scan could take the same time as scan only one device (etc. 30 seconds versus hours). And is excited to find out the simple and powerful usage of xargs -P option.
Here are man xargs result regarding -P:
-P max-procs, --max-procs=max-procs
Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time. Use the -n option or the -L option with -P; otherwise chances are that only one exec will be done.
Put together into my small script:
#!/usr/bin/bash
echo >/tmp/list
subnets="192.168.4 192.168.6 192.168.7 192.168.14 192.168.15"
(for j in $subnets; do for i in {1..254}; do echo $j.$i; done;done) | xargs -P 12000 -n 1 expect checkscripts >> /tmp/list
And woola, now scanning through all these subnets still only takes 30 seconds.
Then I integrates Google Table (Thanks!) into the result and now I get an sort-able table with all the results. Great!
Next step, of course, would be add this as a cronjob and also add an function to allow dynamic update via PHP, this actually did not finish running the whole scans, giving me only partial results along with the following error log:
And it took me a while to figure this out. The reason is by default crond and apache2 process could only handle 512 concurrent processes, which you could check from this sample command here:
systemctl status crond
crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2018-11-20 12:28:28 PST; 5 days ago
Main PID: 803 (crond)
Tasks: 1 (limit: 512)
CGroup: /system.slice/crond.service
And on my Debian server, the command to fix this are:
systemctl set-property apache2.service TasksMax=12000
systemctl set-property cron.service TasksMax=12000
Finally everything is happy and xargs saves the day!
Finally I think it is time to parallel these tasks so the whole scan could take the same time as scan only one device (etc. 30 seconds versus hours). And is excited to find out the simple and powerful usage of xargs -P option.
Here are man xargs result regarding -P:
-P max-procs, --max-procs=max-procs
Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time. Use the -n option or the -L option with -P; otherwise chances are that only one exec will be done.
Put together into my small script:
#!/usr/bin/bash
echo >/tmp/list
subnets="192.168.4 192.168.6 192.168.7 192.168.14 192.168.15"
(for j in $subnets; do for i in {1..254}; do echo $j.$i; done;done) | xargs -P 12000 -n 1 expect checkscripts >> /tmp/list
And woola, now scanning through all these subnets still only takes 30 seconds.
Then I integrates Google Table (Thanks!) into the result and now I get an sort-able table with all the results. Great!
Next step, of course, would be add this as a cronjob and also add an function to allow dynamic update via PHP, this actually did not finish running the whole scans, giving me only partial results along with the following error log:
Resource temporarily unavailable
And it took me a while to figure this out. The reason is by default crond and apache2 process could only handle 512 concurrent processes, which you could check from this sample command here:
systemctl status crond
crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2018-11-20 12:28:28 PST; 5 days ago
Main PID: 803 (crond)
Tasks: 1 (limit: 512)
CGroup: /system.slice/crond.service
And on my Debian server, the command to fix this are:
systemctl set-property apache2.service TasksMax=12000
systemctl set-property cron.service TasksMax=12000
Finally everything is happy and xargs saves the day!