diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-09-09 17:44:16 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-09-09 17:44:16 +0300 |
commit | fb0f0c9767831a373ab6a46781fad52987191c12 (patch) | |
tree | 631b3b88470d69bc2a11fbb0a739791287dbd4ac | |
parent | aeef348db666ab537054a6ab48a75586fc7c6733 (diff) | |
download | genrc-fb0f0c9767831a373ab6a46781fad52987191c12.tar.gz genrc-fb0f0c9767831a373ab6a46781fad52987191c12.tar.bz2 |
New option to limit the runtime resource usage.
* src/genrc.c: Implement the --limit (-l) option.
* NEWS: Update.
* src/genrc.8: Document the --limit option.
-rw-r--r-- | NEWS | 31 | ||||
-rw-r--r-- | src/genrc.8 | 42 | ||||
-rw-r--r-- | src/genrc.c | 103 |
3 files changed, 172 insertions, 4 deletions
@@ -4,7 +4,14 @@ See the end of file for copying conditions. Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua> -* New options +* Verbose diagnostics + +Verbose diagnostics is enabled by the -v,--verbose option. + +* Shell selection + +By default, the program is started using "/bin/sh -c". Two options +are provided to alter this behavior: -s, --shell=SHELL Use SHELL to start the program. Default is /bin/sh. @@ -13,8 +20,9 @@ Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua> In sentinel mode, run the command directly via exec(3), instead of via the shell. - -v,--verbose - Print verbose diagnostics. +* Syslog + +In sentinel mode, the syslog facility and tag can be changed: --log-facility=F Use syslog facility F instead of the default "daemon". @@ -24,6 +32,23 @@ Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua> Use syslog tag S instead of the program name. (equivalent environment variable - GENRC_LOG_TAG) +* Runtime resource limits + +The --limit (-l) option is provided to control the resource usage. +Its argument is a resource designator followed by the limit value +for that resource. Resource designators are: + + c Core file size (KB). + d Data size (KB). + f File size (KB). + l Locked-in-memory address space (KB). + m Resident set size (KB). + n Number of open files. + p Process priority (nice value), -20..20. + s Stack size (KB). + t CPU time (seconds). + u Number of subprocesses. + v Virtual memory size (KB). Version 1.1, 2018-05-20 diff --git a/src/genrc.8 b/src/genrc.8 index 49d8127..c4715da 100644 --- a/src/genrc.8 +++ b/src/genrc.8 @@ -25,6 +25,7 @@ genrc \- generic system initialization script helper [\fB\-P\fR \fISOURCE\fR]\ [\fB\-c\fR \fICOMMAND\fR]\ [\fB\-g\fR \fIGROUP\fR[,\fIGROUP\fR...]]\ + [\fB\-l\fR \fILIMIT\fR]\ [\fB\-p\fR \fIPROGRAM\fR]\ [\fB\-s\fR \fISHELL\fR]\ [\fB\-t\fR \fISECONDS\fR]\ @@ -36,6 +37,7 @@ genrc \- generic system initialization script helper [\fB\-\-help\fR]\ [\fB\-\-log\-facility=\fIFACILITY\fR]\ [\fB\-\-log\-tag=\fITAG\fR]\ + [\fB\-\-limit=\fILIMIT\fR]\ [\fB\-\-no\-reload\fR]\ [\fB\-\-pid\-from=\fISOURCE\fR]\ [\fB\-\-pidfile=\fIPIDFILE\fR]\ @@ -214,6 +216,46 @@ notation is used, the groups must exist in the system group database. See also the \fB\-\-user\fR option. .TP +\fB\-l\fR, \fB\-\-limit=\fILIM\fR +Set resource limit. \fILIM\fR is a resource letter followed by +a value. Resource letters are: +.RS +.TP +.B c +Core file size (KB). +.TP +.B d +Data size (KB). +.TP +.B f +File size (KB). +.TP +.B l +Locked-in-memory address space (KB). +.TP +.B m +Resident set size (KB). +.TP +.B n +Number of open files. +.TP +.B p +Process priority (nice value), -20..20. +.TP +.B s +Stack size (KB). +.TP +.B t +CPU time (seconds). +.TP +.B u +Number of subprocesses. +.TP +.B v +Virtual memory size (KB). +.RE +.TP +.TP \fB\-\-log\-facility=\fIFACILITY\fR Selects \fBsyslog\fR facility for use in sentinel mode. Valid arguments are .BR auth , diff --git a/src/genrc.c b/src/genrc.c index 5f66552..04845d0 100644 --- a/src/genrc.c +++ b/src/genrc.c @@ -7,6 +7,7 @@ There is NO WARRANTY, to the extent permitted by law. #include "genrc.h" #include <syslog.h> #include <sys/ioctl.h> +#include <sys/resource.h> char *genrc_command; char *genrc_program; @@ -58,6 +59,7 @@ struct option longopts[] = { { "restart-on-signal", required_argument, 0, OPT_RESTART_ON_SIGNAL }, { "log-facility", required_argument, 0, OPT_LOG_FACILITY }, { "log-tag", required_argument, 0, OPT_LOG_TAG }, + { "limit", required_argument, 0, 'l' }, { NULL } }; char shortopts[2*sizeof(longopts)/sizeof(longopts[0])]; @@ -212,11 +214,24 @@ char const *help_msg[] = { " Otherwise, if COMMAND is set, but PROGRAM is not, PROGRAM is set to the", " first word (in the shell sense) in COMMAND.", "", - "Runtime privileges:", + "Runtime privileges and limits:", "", " -u, --user=NAME run with this user privileges", " -g, --group=GROUP[,GROUP...]]", " run with this group(s) privileges", + " -l, --limit=LIM set resource limit; LIM is a resource letter", + " followed by the resource value; resource letters are:", + " c core file size (KB)", + " d data size (KB)", + " f file size (KB)", + " l locked-in-memory address space (KB)", + " m resident set size (KB)", + " n number of open files", + " p process priority -20..20", + " s stack size (KB)", + " t CPU time (seconds)", + " u number of subprocesses", + " v virtual memory (KB)", "", "Additional configuration:", "", @@ -318,6 +333,7 @@ char const *usage_msg[] = { "[-P SOURCE]", "[-c COMMAND]", "[-g GROUP[,GROUP...]]", + "[-l LIM]", "[-p PROGRAM]", "[-s SHELL]", "[-t SECONDS]", @@ -325,6 +341,7 @@ char const *usage_msg[] = { "[--command=COMMAND]", "[--group GROUP[,GROUP...]]", "[--help]", + "[--limit=LIM]", "[--log-facility=FACILITY]", "[--log-tag=TAG]", "[--no-reload]", @@ -370,6 +387,84 @@ screen_width(void) return ws.ws_col; } +static struct { + int letter; + int resource; + int is_set; + long val; +} resource_tab[] = { + { 'c', RLIMIT_CORE }, + { 'd', RLIMIT_DATA }, + { 'f', RLIMIT_FSIZE }, + { 'l', RLIMIT_MEMLOCK }, + { 'm', RLIMIT_RSS }, + { 'n', RLIMIT_NOFILE }, + { 's', RLIMIT_STACK }, + { 't', RLIMIT_CPU }, + { 'u', RLIMIT_NPROC }, + { 'v', RLIMIT_AS }, + { 'p', 0 } +}; + +static int +find_resource(int letter) +{ + int i; + for (i = 0; i < sizeof(resource_tab)/sizeof(resource_tab[0]); i++) + if (letter == resource_tab[i].letter) + return resource_tab[i].resource; + return -1; +} + +void +set_limit(char *arg) +{ + int r; + unsigned long v; + char *p; + struct rlimit rlim; + + if ((r = find_resource(arg[0])) == -1) { + usage_error("%s: unrecognized resource code", arg); + } + if ((v = strtoul(arg + 1, &p, 10)) == ULONG_MAX && errno == ERANGE) { + usage_error("%s: resource value out of range", arg); + } + if (*p) { + usage_error("%s: value is not a number (stopped at %s)", + arg, p); + } + + v *= 1024; + rlim.rlim_cur = v; + rlim.rlim_max = v; + if (setrlimit(r, &rlim)) + genrc_error("%s: failed to set limit: %s", arg, + strerror(errno)); +} + +void +set_nice(char *arg) +{ + long v; + char *p; + + if ((((v = strtol(arg + 1, &p, 10)) == LONG_MAX || v == LONG_MIN) + && errno == ERANGE) || + v < -20 || + v > 20) { + usage_error("%s: resource value out of range", arg); + } + if (*p) { + usage_error("%s: value is not a number (stopped at %s)", + arg, p); + } + if (setpriority (PRIO_PROCESS, 0, v)) { + usage_error("failed to set process priority: %s", + strerror(errno)); + } +} + void usage(void) { @@ -503,6 +598,12 @@ main(int argc, char **argv) case 'e': genrc_shell = NULL; break; + case 'l': + if (optarg[0] == 'p') + set_nice(optarg+1); + else + set_limit(optarg); + break; case 's': if (strcmp(optarg, "no") == 0 || strcmp(optarg, "none") == 0) |