Please help me to find out how to limit number of program concurrent executions. I mean, particular program can be ran only, for example 5 times at once. I know how to limit proccess number for user, but how to do that for program, using PAM?
Limit number of program executions
executablelimit
Related Solutions
Split urls into one file per host. Then run 'parallel -j5' on each file.
Or sort urls and insert a delimiter '\0' when a new host is met, then split on '\0' and remove '\0' while passing that as a block to a new instance of parallel:
sort urls.txt |
perl -pe '(not m://$last:) and print "\0";m://([^/]+): and $last=$1' |
parallel -j10 --pipe --rrs -N1 --recend '\0' parallel -j5 ./scan
Edit:
I think this will work:
cat urls.txt | parallel -q -j50 sem --fg --id '{= m://([^/]+):; $_=$1 =}' -j5 ./scan {}
sem
is part of GNU Parallel (it is a shorthand for parallel --semaphore
). {= m://([^/]+):; $_=$1 =}
grabs the hostname. -j5
tells sem
to make a counting semaphore with 5 slots. --fg
forces sem
to not spawn the job in the background. By using the hostname as ID you will get a counting semaphore for each hostname.
-q
is needed for parallel
if some of your URLs contain special shell chars (such as &). They need to be protected from shell expansion because sem
will also shell expand them.
This would be hacky, but if it's a dynamically linked executable, you could set up a global preload in /etc/ld.so.preload
which would only trigger a logging hook if it detected you were in the right executable.
Something like:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define TARGET "/some_executable"
__attribute__((constructor))
static void
logger(int argc, char** argv){
/*catch own argv right here and parent's later from /proc */
static char buf[sizeof(TARGET)];
readlink("/proc/self/exe", buf, sizeof(buf)-1);
if ( 0==strcmp(TARGET, buf)){
/* ... */
syslog(/*...*/);
}
}
The obvious disadvantage of this approach is it would slightly delay the execution of each dynamically linked executable on your system, but my measurements indicate the delay is quite small (<1ms where fork+exec costs about 2ms).
As for the dropped permission problem, you could have a small setuid-root binary that will unconditionally read and echo its grandparents proc files (the status
file, most likely), possibly if and only if its parent is the executable whose parents you want to log. You could then spawn that setuid executable inside your logging hook to obtain the info on the executables parent (grandparent of the setuid helper).
Best Answer
PAM is used to authorize logins and account modifications. It is not at all relevant to restricting a specific program.
The only way to apply a limit to the number of times a program can be executed is to invoke it through a wrapper that applies this limit. Users can of course bypass this wrapper by having their own copy of the program; if you don't want that, don't give those users account on your machine.
To restrict a program to a single instance, you can make it take an exclusive lock on a file. There's no straightforward way to use a file to allow a limited number of instances, but you can use 5 files to allow 5 instances, and make the wrapper script try each file in turn. Create a directory
/var/lib/myapp/instances
(or wherever you want to put it) and create 5 files in it, all world-readable but only writable by root.Wrapper script (replace
myapp.original
by the path to the original executable), using Linux'sflock
utility: