diff options
author | James Byrne <james.byrne at origamienergy.com> | 2017-05-15 21:39:51 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-05-15 21:40:18 +0200 |
commit | 0c63299b84513ff995413f820cb5f3d546c0c5d7 (patch) | |
tree | 97da88d8a741ce485ecf0e767c030296135e817f | |
parent | bcb5764822b07f2f1f6a5db355566ac1da70ac5b (diff) | |
download | busybox-w32-0c63299b84513ff995413f820cb5f3d546c0c5d7.tar.gz busybox-w32-0c63299b84513ff995413f820cb5f3d546c0c5d7.tar.bz2 busybox-w32-0c63299b84513ff995413f820cb5f3d546c0c5d7.zip |
sv: update to match version 2.1.2 of runit
Backport from upstream versions:
2.1.2
Sun, 10 Aug 2014 18:01:54 +0000
* sv.c: properly format status command's output on failure cases.
* sv.c: support optional LSB init script actions reload and
try-restart.
* sv.c: fix typo that may lead to wrong output from sv when reporting
status of multiple service directories.
2.1.1
Sun, 04 Oct 2009 20:28:38 +0000
* sv.c: on 'down', send runsv the 'down' command properly if not yet
done (e.g. when taken up with 'once').
[Remove previous workaround added to BusyBox version].
1.9.0
Mon, 05 May 2008 22:00:13 +0000
* sv.c: service name is also relative to the current directory if it
ends with a slash.
1.8.0
Fri, 21 Sep 2007 00:33:56 +0000
* sv.c: fix race on check for down if pid is 0 and state is run or
finish.
1.7.1
Sat, 04 Nov 2006 19:23:29 +0000
* sv.c: properly wait for a service to be restarted on 'restart';
support checks through -v for pause, cont, kill.
function old new delta
sv 1184 1280 +96
control 132 180 +48
status 118 139 +21
out 64 85 +21
svstatus_print 334 344 +10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/0 up/down: 196/0) Total: 196 bytes
Signed-off-by: James Byrne <james.byrne at origamienergy.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | runit/sv.c | 163 |
1 files changed, 98 insertions, 65 deletions
diff --git a/runit/sv.c b/runit/sv.c index 64f1ae395..faa31d4fa 100644 --- a/runit/sv.c +++ b/runit/sv.c | |||
@@ -25,7 +25,7 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* Taken from http://smarden.sunsite.dk/runit/sv.8.html: | 28 | /* Taken from http://smarden.org/runit/sv.8.html: |
29 | 29 | ||
30 | sv - control and manage services monitored by runsv | 30 | sv - control and manage services monitored by runsv |
31 | 31 | ||
@@ -36,17 +36,13 @@ The sv program reports the current status and controls the state of services | |||
36 | monitored by the runsv(8) supervisor. | 36 | monitored by the runsv(8) supervisor. |
37 | 37 | ||
38 | services consists of one or more arguments, each argument naming a directory | 38 | services consists of one or more arguments, each argument naming a directory |
39 | service used by runsv(8). If service doesn't start with a dot or slash, | 39 | service used by runsv(8). If service doesn't start with a dot or slash and |
40 | it is searched in the default services directory /var/service/, otherwise | 40 | doesn't end with a slash, it is searched in the default services directory |
41 | relative to the current directory. | 41 | /var/service/, otherwise relative to the current directory. |
42 | 42 | ||
43 | command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, | 43 | command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, |
44 | 1, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, | 44 | 1, 2, term, kill, or exit, or start, stop, reload, restart, shutdown, |
45 | force-reload, force-restart, force-shutdown. | 45 | force-stop, force-reload, force-restart, force-shutdown, try-restart. |
46 | |||
47 | The sv program can be sym-linked to /etc/init.d/ to provide an LSB init | ||
48 | script interface. The service to be controlled then is specified by the | ||
49 | base name of the "init script". | ||
50 | 46 | ||
51 | status | 47 | status |
52 | Report the current status of the service, and the appendant log service | 48 | Report the current status of the service, and the appendant log service |
@@ -66,9 +62,9 @@ exit | |||
66 | If the service is running, send it the TERM signal, and the CONT signal. | 62 | If the service is running, send it the TERM signal, and the CONT signal. |
67 | Do not restart the service. If the service is down, and no log service | 63 | Do not restart the service. If the service is down, and no log service |
68 | exists, runsv(8) exits. If the service is down and a log service exists, | 64 | exists, runsv(8) exits. If the service is down and a log service exists, |
69 | send the TERM signal to the log service. If the log service is down, | 65 | runsv(8) closes the standard input of the log service and waits for it to |
70 | runsv(8) exits. This command is ignored if it is given to an appendant | 66 | terminate. If the log service is down, runsv(8) exits. This command is |
71 | log service. | 67 | ignored if it is given to an appendant log service. |
72 | 68 | ||
73 | sv actually looks only at the first character of above commands. | 69 | sv actually looks only at the first character of above commands. |
74 | 70 | ||
@@ -85,6 +81,8 @@ start | |||
85 | stop | 81 | stop |
86 | Same as down, but wait up to 7 seconds for the service to become down. | 82 | Same as down, but wait up to 7 seconds for the service to become down. |
87 | Then report the status or timeout. | 83 | Then report the status or timeout. |
84 | reload | ||
85 | Same as hup, and additionally report the status afterwards. | ||
88 | restart | 86 | restart |
89 | Send the commands term, cont, and up to the service, and wait up to | 87 | Send the commands term, cont, and up to the service, and wait up to |
90 | 7 seconds for the service to restart. Then report the status or timeout. | 88 | 7 seconds for the service to restart. Then report the status or timeout. |
@@ -112,6 +110,9 @@ force-shutdown | |||
112 | Same as exit, but wait up to 7 seconds for the runsv(8) process to | 110 | Same as exit, but wait up to 7 seconds for the runsv(8) process to |
113 | terminate. Then report the status, and on timeout send the service | 111 | terminate. Then report the status, and on timeout send the service |
114 | the kill command. | 112 | the kill command. |
113 | try-restart | ||
114 | if the service is running, send it the term and cont commands, and wait up to | ||
115 | 7 seconds for the service to restart. Then report the status or timeout. | ||
115 | 116 | ||
116 | Additional Commands | 117 | Additional Commands |
117 | 118 | ||
@@ -126,8 +127,8 @@ check | |||
126 | Options | 127 | Options |
127 | 128 | ||
128 | -v | 129 | -v |
129 | wait up to 7 seconds for the command to take effect. | 130 | If the command is up, down, term, once, cont, or exit, then wait up to 7 |
130 | Then report the status or timeout. | 131 | seconds for the command to take effect. Then report the status or timeout. |
131 | -w sec | 132 | -w sec |
132 | Override the default timeout of 7 seconds with sec seconds. Implies -v. | 133 | Override the default timeout of 7 seconds with sec seconds. Implies -v. |
133 | 134 | ||
@@ -192,6 +193,7 @@ struct globals { | |||
192 | /* "Bernstein" time format: unix + 0x400000000000000aULL */ | 193 | /* "Bernstein" time format: unix + 0x400000000000000aULL */ |
193 | uint64_t tstart, tnow; | 194 | uint64_t tstart, tnow; |
194 | svstatus_t svstatus; | 195 | svstatus_t svstatus; |
196 | unsigned islog; | ||
195 | } FIX_ALIASING; | 197 | } FIX_ALIASING; |
196 | #define G (*(struct globals*)bb_common_bufsiz1) | 198 | #define G (*(struct globals*)bb_common_bufsiz1) |
197 | #define acts (G.acts ) | 199 | #define acts (G.acts ) |
@@ -200,6 +202,7 @@ struct globals { | |||
200 | #define tstart (G.tstart ) | 202 | #define tstart (G.tstart ) |
201 | #define tnow (G.tnow ) | 203 | #define tnow (G.tnow ) |
202 | #define svstatus (G.svstatus ) | 204 | #define svstatus (G.svstatus ) |
205 | #define islog (G.islog ) | ||
203 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 206 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
204 | 207 | ||
205 | 208 | ||
@@ -215,7 +218,7 @@ static void fatal_cannot(const char *m1) | |||
215 | 218 | ||
216 | static void out(const char *p, const char *m1) | 219 | static void out(const char *p, const char *m1) |
217 | { | 220 | { |
218 | printf("%s%s: %s", p, *service, m1); | 221 | printf("%s%s%s: %s", p, *service, islog ? "/log" : "", m1); |
219 | if (errno) { | 222 | if (errno) { |
220 | printf(": %s", strerror(errno)); | 223 | printf(": %s", strerror(errno)); |
221 | } | 224 | } |
@@ -300,15 +303,14 @@ static unsigned svstatus_print(const char *m) | |||
300 | } | 303 | } |
301 | pid = SWAP_LE32(svstatus.pid_le32); | 304 | pid = SWAP_LE32(svstatus.pid_le32); |
302 | timestamp = SWAP_BE64(svstatus.time_be64); | 305 | timestamp = SWAP_BE64(svstatus.time_be64); |
303 | if (pid) { | 306 | switch (svstatus.run_or_finish) { |
304 | switch (svstatus.run_or_finish) { | 307 | case 0: printf("down: "); break; |
305 | case 1: printf("run: "); break; | 308 | case 1: printf("run: "); break; |
306 | case 2: printf("finish: "); break; | 309 | case 2: printf("finish: "); break; |
307 | } | ||
308 | printf("%s: (pid %d) ", m, pid); | ||
309 | } else { | ||
310 | printf("down: %s: ", m); | ||
311 | } | 310 | } |
311 | printf("%s: ", m); | ||
312 | if (svstatus.run_or_finish) | ||
313 | printf("(pid %d) ", pid); | ||
312 | diff = tnow - timestamp; | 314 | diff = tnow - timestamp; |
313 | printf("%us", (diff < 0 ? 0 : diff)); | 315 | printf("%us", (diff < 0 ? 0 : diff)); |
314 | if (pid) { | 316 | if (pid) { |
@@ -331,16 +333,21 @@ static int status(const char *unused UNUSED_PARAM) | |||
331 | return 0; | 333 | return 0; |
332 | 334 | ||
333 | r = svstatus_print(*service); | 335 | r = svstatus_print(*service); |
336 | islog = 1; | ||
334 | if (chdir("log") == -1) { | 337 | if (chdir("log") == -1) { |
335 | if (errno != ENOENT) { | 338 | if (errno != ENOENT) { |
336 | printf("; log: "WARN"can't change to log service directory: %s", | 339 | printf("; "); |
337 | strerror(errno)); | 340 | warn("can't change directory"); |
338 | } | 341 | } else |
339 | } else if (svstatus_get()) { | 342 | bb_putchar('\n'); |
343 | } else { | ||
340 | printf("; "); | 344 | printf("; "); |
341 | svstatus_print("log"); | 345 | if (svstatus_get()) { |
346 | r = svstatus_print("log"); | ||
347 | bb_putchar('\n'); | ||
348 | } | ||
342 | } | 349 | } |
343 | bb_putchar('\n'); /* will also flush the output */ | 350 | islog = 0; |
344 | return r; | 351 | return r; |
345 | } | 352 | } |
346 | 353 | ||
@@ -379,35 +386,53 @@ static int check(const char *a) | |||
379 | r = svstatus_get(); | 386 | r = svstatus_get(); |
380 | if (r == -1) | 387 | if (r == -1) |
381 | return -1; | 388 | return -1; |
382 | if (r == 0) { | 389 | while (*a) { |
383 | if (*a == 'x') | 390 | if (r == 0) { |
384 | return 1; | 391 | if (*a == 'x') |
385 | return -1; | 392 | return 1; |
386 | } | 393 | return -1; |
387 | pid_le32 = svstatus.pid_le32; | 394 | } |
388 | switch (*a) { | 395 | pid_le32 = svstatus.pid_le32; |
389 | case 'x': | 396 | switch (*a) { |
390 | return 0; | 397 | case 'x': |
391 | case 'u': | ||
392 | if (!pid_le32 || svstatus.run_or_finish != 1) return 0; | ||
393 | if (!checkscript()) return 0; | ||
394 | break; | ||
395 | case 'd': | ||
396 | if (pid_le32) return 0; | ||
397 | break; | ||
398 | case 'c': | ||
399 | if (pid_le32 && !checkscript()) return 0; | ||
400 | break; | ||
401 | case 't': | ||
402 | if (!pid_le32 && svstatus.want == 'd') break; | ||
403 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
404 | if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) | ||
405 | return 0; | ||
406 | break; | ||
407 | case 'o': | ||
408 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
409 | if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) | ||
410 | return 0; | 398 | return 0; |
399 | case 'u': | ||
400 | if (!pid_le32 || svstatus.run_or_finish != 1) | ||
401 | return 0; | ||
402 | if (!checkscript()) | ||
403 | return 0; | ||
404 | break; | ||
405 | case 'd': | ||
406 | if (pid_le32 || svstatus.run_or_finish != 0) | ||
407 | return 0; | ||
408 | break; | ||
409 | case 'C': | ||
410 | if (pid_le32 && !checkscript()) | ||
411 | return 0; | ||
412 | break; | ||
413 | case 't': | ||
414 | case 'k': | ||
415 | if (!pid_le32 && svstatus.want == 'd') | ||
416 | break; | ||
417 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
418 | if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) | ||
419 | return 0; | ||
420 | break; | ||
421 | case 'o': | ||
422 | timestamp = SWAP_BE64(svstatus.time_be64); | ||
423 | if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) | ||
424 | return 0; | ||
425 | break; | ||
426 | case 'p': | ||
427 | if (pid_le32 && !svstatus.paused) | ||
428 | return 0; | ||
429 | break; | ||
430 | case 'c': | ||
431 | if (pid_le32 && svstatus.paused) | ||
432 | return 0; | ||
433 | break; | ||
434 | } | ||
435 | ++a; | ||
411 | } | 436 | } |
412 | printf(OK); | 437 | printf(OK); |
413 | svstatus_print(*service); | 438 | svstatus_print(*service); |
@@ -419,14 +444,10 @@ static int control(const char *a) | |||
419 | { | 444 | { |
420 | int fd, r, l; | 445 | int fd, r, l; |
421 | 446 | ||
422 | /* Is it an optimization? | ||
423 | It causes problems with "sv o SRV; ...; sv d SRV" | ||
424 | ('d' is not passed to SRV because its .want == 'd'): | ||
425 | if (svstatus_get() <= 0) | 447 | if (svstatus_get() <= 0) |
426 | return -1; | 448 | return -1; |
427 | if (svstatus.want == *a) | 449 | if (svstatus.want == *a && (*a != 'd' || svstatus.got_term == 1)) |
428 | return 0; | 450 | return 0; |
429 | */ | ||
430 | fd = open("supervise/control", O_WRONLY|O_NDELAY); | 451 | fd = open("supervise/control", O_WRONLY|O_NDELAY); |
431 | if (fd == -1) { | 452 | if (fd == -1) { |
432 | if (errno != ENODEV) | 453 | if (errno != ENODEV) |
@@ -516,17 +537,23 @@ static int sv(char **argv) | |||
516 | acts = "tc"; | 537 | acts = "tc"; |
517 | kll = 1; | 538 | kll = 1; |
518 | break; | 539 | break; |
540 | case 't': | ||
541 | if (str_equal(action, "try-restart")) { | ||
542 | acts = "tc"; | ||
543 | break; | ||
544 | } | ||
519 | case 'c': | 545 | case 'c': |
520 | if (str_equal(action, "check")) { | 546 | if (str_equal(action, "check")) { |
521 | act = NULL; | 547 | act = NULL; |
522 | acts = "c"; | 548 | acts = "C"; |
523 | break; | 549 | break; |
524 | } | 550 | } |
525 | case 'u': case 'd': case 'o': case 't': case 'p': case 'h': | 551 | case 'u': case 'd': case 'o': case 'p': case 'h': |
526 | case 'a': case 'i': case 'k': case 'q': case '1': case '2': | 552 | case 'a': case 'i': case 'k': case 'q': case '1': case '2': |
527 | action[1] = '\0'; | 553 | action[1] = '\0'; |
528 | acts = action; | 554 | acts = action; |
529 | if (!verbose) cbk = NULL; | 555 | if (!verbose) |
556 | cbk = NULL; | ||
530 | break; | 557 | break; |
531 | case 's': | 558 | case 's': |
532 | if (str_equal(action, "shutdown")) { | 559 | if (str_equal(action, "shutdown")) { |
@@ -550,6 +577,10 @@ static int sv(char **argv) | |||
550 | acts = "tcu"; | 577 | acts = "tcu"; |
551 | break; | 578 | break; |
552 | } | 579 | } |
580 | if (str_equal(action, "reload")) { | ||
581 | acts = "h"; | ||
582 | break; | ||
583 | } | ||
553 | bb_show_usage(); | 584 | bb_show_usage(); |
554 | case 'f': | 585 | case 'f': |
555 | if (str_equal(action, "force-reload")) { | 586 | if (str_equal(action, "force-reload")) { |
@@ -578,7 +609,9 @@ static int sv(char **argv) | |||
578 | 609 | ||
579 | service = argv; | 610 | service = argv; |
580 | while ((x = *service) != NULL) { | 611 | while ((x = *service) != NULL) { |
581 | if (x[0] != '/' && x[0] != '.') { | 612 | if (x[0] != '/' && x[0] != '.' |
613 | && x[0] != '\0' && x[strlen(x) - 1] != '/' | ||
614 | ) { | ||
582 | if (chdir(varservice) == -1) | 615 | if (chdir(varservice) == -1) |
583 | goto chdir_failed_0; | 616 | goto chdir_failed_0; |
584 | } | 617 | } |