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>
This commit is contained in:
James Byrne 2017-05-15 21:39:51 +02:00 committed by Denys Vlasenko
parent bcb5764822
commit 0c63299b84

View File

@ -25,7 +25,7 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* Taken from http://smarden.sunsite.dk/runit/sv.8.html: /* Taken from http://smarden.org/runit/sv.8.html:
sv - control and manage services monitored by runsv sv - control and manage services monitored by runsv
@ -36,17 +36,13 @@ The sv program reports the current status and controls the state of services
monitored by the runsv(8) supervisor. monitored by the runsv(8) supervisor.
services consists of one or more arguments, each argument naming a directory services consists of one or more arguments, each argument naming a directory
service used by runsv(8). If service doesn't start with a dot or slash, service used by runsv(8). If service doesn't start with a dot or slash and
it is searched in the default services directory /var/service/, otherwise doesn't end with a slash, it is searched in the default services directory
relative to the current directory. /var/service/, otherwise relative to the current directory.
command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, command is one of up, down, status, once, pause, cont, hup, alarm, interrupt,
1, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, 1, 2, term, kill, or exit, or start, stop, reload, restart, shutdown,
force-reload, force-restart, force-shutdown. force-stop, force-reload, force-restart, force-shutdown, try-restart.
The sv program can be sym-linked to /etc/init.d/ to provide an LSB init
script interface. The service to be controlled then is specified by the
base name of the "init script".
status status
Report the current status of the service, and the appendant log service Report the current status of the service, and the appendant log service
@ -66,9 +62,9 @@ exit
If the service is running, send it the TERM signal, and the CONT signal. If the service is running, send it the TERM signal, and the CONT signal.
Do not restart the service. If the service is down, and no log service Do not restart the service. If the service is down, and no log service
exists, runsv(8) exits. If the service is down and a log service exists, exists, runsv(8) exits. If the service is down and a log service exists,
send the TERM signal to the log service. If the log service is down, runsv(8) closes the standard input of the log service and waits for it to
runsv(8) exits. This command is ignored if it is given to an appendant terminate. If the log service is down, runsv(8) exits. This command is
log service. ignored if it is given to an appendant log service.
sv actually looks only at the first character of above commands. sv actually looks only at the first character of above commands.
@ -85,6 +81,8 @@ start
stop stop
Same as down, but wait up to 7 seconds for the service to become down. Same as down, but wait up to 7 seconds for the service to become down.
Then report the status or timeout. Then report the status or timeout.
reload
Same as hup, and additionally report the status afterwards.
restart restart
Send the commands term, cont, and up to the service, and wait up to Send the commands term, cont, and up to the service, and wait up to
7 seconds for the service to restart. Then report the status or timeout. 7 seconds for the service to restart. Then report the status or timeout.
@ -112,6 +110,9 @@ force-shutdown
Same as exit, but wait up to 7 seconds for the runsv(8) process to Same as exit, but wait up to 7 seconds for the runsv(8) process to
terminate. Then report the status, and on timeout send the service terminate. Then report the status, and on timeout send the service
the kill command. the kill command.
try-restart
if the service is running, send it the term and cont commands, and wait up to
7 seconds for the service to restart. Then report the status or timeout.
Additional Commands Additional Commands
@ -126,8 +127,8 @@ check
Options Options
-v -v
wait up to 7 seconds for the command to take effect. If the command is up, down, term, once, cont, or exit, then wait up to 7
Then report the status or timeout. seconds for the command to take effect. Then report the status or timeout.
-w sec -w sec
Override the default timeout of 7 seconds with sec seconds. Implies -v. Override the default timeout of 7 seconds with sec seconds. Implies -v.
@ -192,6 +193,7 @@ struct globals {
/* "Bernstein" time format: unix + 0x400000000000000aULL */ /* "Bernstein" time format: unix + 0x400000000000000aULL */
uint64_t tstart, tnow; uint64_t tstart, tnow;
svstatus_t svstatus; svstatus_t svstatus;
unsigned islog;
} FIX_ALIASING; } FIX_ALIASING;
#define G (*(struct globals*)bb_common_bufsiz1) #define G (*(struct globals*)bb_common_bufsiz1)
#define acts (G.acts ) #define acts (G.acts )
@ -200,6 +202,7 @@ struct globals {
#define tstart (G.tstart ) #define tstart (G.tstart )
#define tnow (G.tnow ) #define tnow (G.tnow )
#define svstatus (G.svstatus ) #define svstatus (G.svstatus )
#define islog (G.islog )
#define INIT_G() do { setup_common_bufsiz(); } while (0) #define INIT_G() do { setup_common_bufsiz(); } while (0)
@ -215,7 +218,7 @@ static void fatal_cannot(const char *m1)
static void out(const char *p, const char *m1) static void out(const char *p, const char *m1)
{ {
printf("%s%s: %s", p, *service, m1); printf("%s%s%s: %s", p, *service, islog ? "/log" : "", m1);
if (errno) { if (errno) {
printf(": %s", strerror(errno)); printf(": %s", strerror(errno));
} }
@ -300,15 +303,14 @@ static unsigned svstatus_print(const char *m)
} }
pid = SWAP_LE32(svstatus.pid_le32); pid = SWAP_LE32(svstatus.pid_le32);
timestamp = SWAP_BE64(svstatus.time_be64); timestamp = SWAP_BE64(svstatus.time_be64);
if (pid) { switch (svstatus.run_or_finish) {
switch (svstatus.run_or_finish) { case 0: printf("down: "); break;
case 1: printf("run: "); break; case 1: printf("run: "); break;
case 2: printf("finish: "); break; case 2: printf("finish: "); break;
}
printf("%s: (pid %d) ", m, pid);
} else {
printf("down: %s: ", m);
} }
printf("%s: ", m);
if (svstatus.run_or_finish)
printf("(pid %d) ", pid);
diff = tnow - timestamp; diff = tnow - timestamp;
printf("%us", (diff < 0 ? 0 : diff)); printf("%us", (diff < 0 ? 0 : diff));
if (pid) { if (pid) {
@ -331,16 +333,21 @@ static int status(const char *unused UNUSED_PARAM)
return 0; return 0;
r = svstatus_print(*service); r = svstatus_print(*service);
islog = 1;
if (chdir("log") == -1) { if (chdir("log") == -1) {
if (errno != ENOENT) { if (errno != ENOENT) {
printf("; log: "WARN"can't change to log service directory: %s", printf("; ");
strerror(errno)); warn("can't change directory");
} } else
} else if (svstatus_get()) { bb_putchar('\n');
} else {
printf("; "); printf("; ");
svstatus_print("log"); if (svstatus_get()) {
r = svstatus_print("log");
bb_putchar('\n');
}
} }
bb_putchar('\n'); /* will also flush the output */ islog = 0;
return r; return r;
} }
@ -379,35 +386,53 @@ static int check(const char *a)
r = svstatus_get(); r = svstatus_get();
if (r == -1) if (r == -1)
return -1; return -1;
if (r == 0) { while (*a) {
if (*a == 'x') if (r == 0) {
return 1; if (*a == 'x')
return -1; return 1;
} return -1;
pid_le32 = svstatus.pid_le32; }
switch (*a) { pid_le32 = svstatus.pid_le32;
case 'x': switch (*a) {
return 0; case 'x':
case 'u':
if (!pid_le32 || svstatus.run_or_finish != 1) return 0;
if (!checkscript()) return 0;
break;
case 'd':
if (pid_le32) return 0;
break;
case 'c':
if (pid_le32 && !checkscript()) return 0;
break;
case 't':
if (!pid_le32 && svstatus.want == 'd') break;
timestamp = SWAP_BE64(svstatus.time_be64);
if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript())
return 0;
break;
case 'o':
timestamp = SWAP_BE64(svstatus.time_be64);
if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd'))
return 0; return 0;
case 'u':
if (!pid_le32 || svstatus.run_or_finish != 1)
return 0;
if (!checkscript())
return 0;
break;
case 'd':
if (pid_le32 || svstatus.run_or_finish != 0)
return 0;
break;
case 'C':
if (pid_le32 && !checkscript())
return 0;
break;
case 't':
case 'k':
if (!pid_le32 && svstatus.want == 'd')
break;
timestamp = SWAP_BE64(svstatus.time_be64);
if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript())
return 0;
break;
case 'o':
timestamp = SWAP_BE64(svstatus.time_be64);
if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd'))
return 0;
break;
case 'p':
if (pid_le32 && !svstatus.paused)
return 0;
break;
case 'c':
if (pid_le32 && svstatus.paused)
return 0;
break;
}
++a;
} }
printf(OK); printf(OK);
svstatus_print(*service); svstatus_print(*service);
@ -419,14 +444,10 @@ static int control(const char *a)
{ {
int fd, r, l; int fd, r, l;
/* Is it an optimization?
It causes problems with "sv o SRV; ...; sv d SRV"
('d' is not passed to SRV because its .want == 'd'):
if (svstatus_get() <= 0) if (svstatus_get() <= 0)
return -1; return -1;
if (svstatus.want == *a) if (svstatus.want == *a && (*a != 'd' || svstatus.got_term == 1))
return 0; return 0;
*/
fd = open("supervise/control", O_WRONLY|O_NDELAY); fd = open("supervise/control", O_WRONLY|O_NDELAY);
if (fd == -1) { if (fd == -1) {
if (errno != ENODEV) if (errno != ENODEV)
@ -516,17 +537,23 @@ static int sv(char **argv)
acts = "tc"; acts = "tc";
kll = 1; kll = 1;
break; break;
case 't':
if (str_equal(action, "try-restart")) {
acts = "tc";
break;
}
case 'c': case 'c':
if (str_equal(action, "check")) { if (str_equal(action, "check")) {
act = NULL; act = NULL;
acts = "c"; acts = "C";
break; break;
} }
case 'u': case 'd': case 'o': case 't': case 'p': case 'h': case 'u': case 'd': case 'o': case 'p': case 'h':
case 'a': case 'i': case 'k': case 'q': case '1': case '2': case 'a': case 'i': case 'k': case 'q': case '1': case '2':
action[1] = '\0'; action[1] = '\0';
acts = action; acts = action;
if (!verbose) cbk = NULL; if (!verbose)
cbk = NULL;
break; break;
case 's': case 's':
if (str_equal(action, "shutdown")) { if (str_equal(action, "shutdown")) {
@ -550,6 +577,10 @@ static int sv(char **argv)
acts = "tcu"; acts = "tcu";
break; break;
} }
if (str_equal(action, "reload")) {
acts = "h";
break;
}
bb_show_usage(); bb_show_usage();
case 'f': case 'f':
if (str_equal(action, "force-reload")) { if (str_equal(action, "force-reload")) {
@ -578,7 +609,9 @@ static int sv(char **argv)
service = argv; service = argv;
while ((x = *service) != NULL) { while ((x = *service) != NULL) {
if (x[0] != '/' && x[0] != '.') { if (x[0] != '/' && x[0] != '.'
&& x[0] != '\0' && x[strlen(x) - 1] != '/'
) {
if (chdir(varservice) == -1) if (chdir(varservice) == -1)
goto chdir_failed_0; goto chdir_failed_0;
} }