Compare commits

...
22 Commits
Author SHA1 Message Date
Joachim Wiberg f483a8aeaa Update ChangeLog and bump version for v4.3 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 21:57:32 +02:00
Joachim Wiberg e3e220ce8e Fix links and update with info on new/existing features
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 21:55:38 +02:00
Joachim Wiberg fc653e4293 man: document initctl cond get
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 20:45:00 +02:00
Joachim Wiberg 94d55cb7dd initctl: allow 'cond get' read any type of condition
Fixes #265

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 11:52:02 +02:00
Joachim Wiberg 0e84ecf143 Minor refactor
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 11:44:24 +02:00
Joachim Wiberg 0e93dfd640 initctl: use standardized exit codes for all fatal errors
This change diversifies the exit codes used by initctl on fatal errors.
Previously only Std C codes 0 and 1 were used, with the initctl specific
255 for some cases.

Both the LSB init script codes and BSD sysexits.h codes are used.  See
util.c exitcodes[] for the full list.  The idea is to complement the
change in 9a76f08, issue #266, so that initctl can be used silently for
scripting purposes.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 11:32:06 +02:00
Joachim Wiberg 4dff8237f1 initctl: fix fallback handling in log command
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 11:01:58 +02:00
Joachim Wiberg 35400f2a8b Minor, drop unused header file
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 10:36:47 +02:00
Joachim Wiberg 9a76f0862c initctl: let -q silence all commands
This patch introduces ERR(), ERRX(), WARN(), and WARNX() as replacements
to their lower case counterparts.  These log macros respect the 'quiet'
flag to initctl, leaving only the return code as indicator to user.

Fixes #266

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 10:34:36 +02:00
Joachim Wiberg fb8a7caa99 initctl: simplify error output of start/stop/restart/signal
No need for the verbose output on error, simply state the cause of the
problem.  The user can issue `initctl -h` to check the syntax of the
command.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 10:30:49 +02:00
Joachim Wiberg f8bed5c7af Minor, fix local shadowing of scope global variable
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 09:38:05 +02:00
Joachim Wiberg da6fa482e7 Follow-up to 195155a, drop unused variable from refactor
... and it's obviously spelled "unlimited", *sigh*

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 09:38:05 +02:00
Joachim Wiberg fdf8e48c99 Minor, reduce scope of local variable
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 09:21:48 +02:00
Joachim Wiberg 195155a7f5 initctl: make log command unlimented
Drop `| tail -10` from 'log foo' command.  Let user call tail themselves
and only limit with tail on status command.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-13 13:53:38 +02:00
Joachim Wiberg 6934ba4dbc initctl: improve log digger in 'status foo' command
Grep in /var/log/syslog, or messages, for both the service identity (not
just svc->cmd) and also try to find [PID] for more relevant information.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-13 13:38:26 +02:00
Joachim Wiberg fdbd25c1b5 Use svc_ident() for more cases
- Drop basename() of svc->cmd from remaining code
  - Replace uses of svc->cmd with svc_ident(svc)
  - Use svc_ident() as default log tag

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-13 13:36:33 +02:00
Joachim Wiberg 467f1cca81 initctl: options alphabetically in usage text
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-10 08:11:37 +02:00
Joachim Wiberg d6fdf4a806 README: update initctl usage text
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-10 08:11:37 +02:00
Joachim Wiberg 4be9d97e61 README: make sure to mention auto-disable of cgroups
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-10 08:11:37 +02:00
Joachim Wiberg 021d011493 man: mention the UNIX pipe at least once in every man page
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-10 08:11:37 +02:00
Joachim Wiberg e988d38f71 initctl: minor, fix indentation in usage text
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-10 08:06:13 +02:00
Joachim Wiberg 8690fc732b Fix #263: document confusing initctl reload foo command
What a ride, apparently we support restarting run/tasks in the same
runlevel they have already started once in.  Still unsure if adding
support for reloading a particular Finit .conf file for a service
should be in the context of this command (it isn't now).  Maybe it
is better left as a future expansion when we switch to the new .conf
format?

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-10 08:03:36 +02:00
14 changed files with 266 additions and 170 deletions
+16 -2
View File
@@ -4,7 +4,7 @@ Change Log
All relevant changes are documented in this file.
[4.3][UNRELEASED]
[4.3][] - 2022-05-15
--------------------
Critical bug fix release. If you run a 32-bit target with GLIBC 2.34
@@ -63,6 +63,14 @@ you *need* to upgrade!
* Document secret service option `respawn`, which bypasses the crash
semantics, allowing endless restarts
* Document secret `HOOK_BANNER`, the first hook point before the banner
* Document slightly confusing `initctl reload foo` command. It does
*not* reload the service's `.conf` file! Issue #263
* Log changes; all instances where previously the `basename cmd` of a
service was used to identify the service, now the proper `name:id` is
used instead. Meaning, a service without a custom `:ID` or `name:`
will display the same as before, but with any of those customizations
the name and name:id will now be shown. **Note:** this may affect any
log scrapers out there!
* New plugin: `hook-scripts`, allows [run-parts(8)][] style scripts to
run on any hook point. Contributed by Tobias Waldekranz
* `initctl` (`reboot`) falls back to `-f` when it detects it is in
@@ -75,6 +83,12 @@ you *need* to upgrade!
in lexicographic order and UNIX backup files (`foo.conf~`) are skipped
* The `name:id` tuple is now more consistently used in all log and debug
messages instead of the basename of the command
* Simplify error output of `initctl start/stop/restart/signal`, no more
extra usage help, just a plain error message
* Exit codes of `initctl` have changed to use LSB script standard and BSD
sysexits.h exit codes. As before, a non-zero exit is error or missing
* Add support for `initctl -q` to more commands: stop, start, restart,
reload, signal, etc.
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
@@ -93,7 +107,7 @@ you *need* to upgrade!
* Fix #233: initctl shows wrong status for run/task, by Sergio Morlans
and Ming Liu, Atlas Copco
* Fix #248: source `env:file` also in `pre:` and `post` scripts
* Fix #260: drop limit on device name in `Checking filesystem`...` output
* Fix #260: drop limit on device name in `Checking filesystem...` output
* Fix start/stop and monitoring (restart) of SysV init scripts and
forking services, see the updated documentation for details
* Fix call to `swapoff` at shutdown, does not support `-e` flag
+37 -11
View File
@@ -45,6 +45,10 @@ Features include:
* Cgroups v2, both configuration and monitoring in `initctl top`
* Plugin support for customization
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
* Integration with [watchdogd][] for full system supervision
* Logging to kernel ring buffer before `syslogd` has started, see the
recommended [sysklogd][] project for complete logging integration
and how to log to the kernel ring buffer from scripts using `logger`
Focus is on small and embedded systems, although Finit is fully usable
on server and desktop systems as well. For working examples, see the
@@ -52,12 +56,12 @@ on server and desktop systems as well. For working examples, see the
* [Void Linux](contrib/void/),
* [Alpine Linux](contrib/alpine/), and
* [Debian GNU/Linux](contrib/debian/)
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
> **Note:** support for various Linux distributions does not mean Finit
> installs easily on all architectures. The bundled install scripts are
> examples for standard installations, tested on x86_64 systems. Custom
> setups, targeted at embedded systems, can be found in [myLinux][].
> examples for standard installations, tested on amd64 (x86_64) systems.
> Custom setups, for embedded systems, can be found in [myLinux][].
Example
@@ -73,7 +77,11 @@ the [initctl](#commands--status) tool.
host default
# Runlevel to start after bootstrap, 'S', default: 2
runlevel 2
#runlevel 2
# Support for setting global environment variables, using foo=bar syntax
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
#PATH=/usr/bin:/bin:/usr/sbin:/sbin
# Max file size for each log file: 100 kiB, rotate max 4 copies:
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
@@ -102,6 +110,11 @@ service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
#task [S] /etc/init.d/kbd -- Preparing console
# Hidden from boot progress, using empty `--` description
#sysv [S] /etc/init.d/keyboard-setup --
#sysv [S] /etc/init.d/acpid --
#task [S] /etc/init.d/kbd --
# Run start scripts from this directory
# runparts /etc/start.d
@@ -268,8 +281,8 @@ unnecessary overhead, which can be removed at build-time using:
**Cgroups**
Finit supports cgroups v2 and comes with the following default groups
in which services and user sessions are placed in:
Finit supports cgroups v2 and comes with the following default groups in
which services and user sessions are placed in:
/sys/fs/cgroup
|-- init/ # cpu.weight:100
@@ -305,6 +318,10 @@ The `initctl` tool has three commands to help debug and optimize the
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
commands for details.
> **Note:** systems that do not support cgroups, specifically version 2,
> are automatically detected. On such systems the above functionality
> is disabled early at boot.
Runparts & /etc/rc.local
------------------------
@@ -414,24 +431,24 @@ services, called `initctl`. Unlike `telinit` the `initctl` tool does
not return until the given command has fully completed.
```
alpine:~# initctl help
Usage: initctl [OPTIONS] [COMMAND]
Options:
-b, --batch Batch mode, no screen size probing
-c, --create Create missing paths (and files) as needed
-f, --force Ignore missing files and arguments, never prompt
-h, --help This help text
-1, --once Only one lap in commands like 'top'
-p, --plain Use plain table headings, no ctrl chars
-q, --quiet Silent, only return status of command
-t, --no-heading Skip table headings
-v, --verbose Verbose output
-h, --help This help text
-V, --version Show program version
Commands:
debug Toggle Finit (daemon) debug
help This help text
version Show Finit version
version Show program version
ls | list List all .conf in /etc/finit.d
create <CONF> Create .conf in /etc/finit.d/available
@@ -444,6 +461,7 @@ Commands:
reload Reload *.conf in /etc/finit.d (activate changes)
cond set <COND> Set (assert) user-defined condition +usr/COND
cond get <COND> Get status of user-defined condition, see $? and -v
cond clear <COND> Clear (deassert) user-defined condition -usr/COND
cond status Show condition status, default cond command
cond dump Dump all conditions and their status
@@ -451,8 +469,12 @@ Commands:
log [NAME] Show ten last Finit, or NAME, messages from syslog
start <NAME>[:ID] Start service by name, with optional ID
stop <NAME>[:ID] Stop/Pause a running service by name
reload <NAME>[:ID] Reload service by name (SIGHUP or restart)
reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)
This allows restart of run/tasks that have already run
Note: Finit .conf file(s) are *not* reloaded!
restart <NAME>[:ID] Restart (stop/start) service by name
signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID
ident [NAME] Show matching identities for NAME, or all
status <NAME>[:ID] Show service status, by name
status Show status of services, default command
@@ -465,6 +487,8 @@ Commands:
halt Halt system
poweroff Halt and power off system
suspend Suspend system
utmp show Raw dump of UTMP/WTMP db
```
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
@@ -603,7 +627,9 @@ and proposed extensions.
[Joachim Wiberg]: https://troglobit.com
[License]: https://en.wikipedia.org/wiki/MIT_License
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
[GitHub]: https://github.com/troglobit/myLinux/
[myLinux]: https://github.com/troglobit/myLinux/
[watchdogd]: https://github.com/troglobit/watchdogd/
[sysklogd]: https://github.com/troglobit/sysklogd/
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
[GitHub Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
[Coverity Scan]: https://scan.coverity.com/projects/3545
+1 -1
View File
@@ -1,4 +1,4 @@
AC_INIT(Finit, 4.3-rc2, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/projects/finit/)
AC_INIT(Finit, 4.3, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/projects/finit/)
AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
AM_SILENT_RULES([yes])
+46 -4
View File
@@ -24,9 +24,11 @@ This program follows the usual UNIX command line syntax, with long
options starting with two dashes (`-'). The options are as follows:
.Bl -tag -width Ds
.It Fl b, -batch
Batch mode, no screen size probing.
Batch mode, no screen size probing. Useful for scripting.
.It Fl c, -create
Create missing paths (and files) as needed. Useful with the edit command.
Create missing paths (and files) as needed. Useful with the
.Cm edit
command.
.It Fl f, -force
Ignore missing files and arguments, never prompt.
.It Fl h, -help
@@ -64,7 +66,16 @@ files in
Create
.Cm .conf
in
.Pa /etc/finit.d/available
.Pa /etc/finit.d/available .
.Pp
Piping the contents into
.Nm
works as one would expect:
.Bd -literal -offset indent
echo "task name:foo /tmp/foo.sh -- Foo logger" | initctl create foo
initctl enable foo
initctl reload
.Ed
.It Nm Ar delete Ar CONF
Delete
.Cm .conf
@@ -113,6 +124,20 @@ i.e., activates changes
.It Nm Ar cond set Ar COND
Set (assert) user-defined condition,
.Cm +usr/COND
.It Nm Ar cond get Ar COND
Get (quietly) the status of any condition. Defaults to user-defined
condions, but if a slash is detected, e.g.,
.Cm pid/foo
or
.Cm net/eth0/exist ,
then any condition can be read.
.Pp
The command is geared for scripting, check the exit code to get the
status of the condition, or give
.Nm
the
.Fl v
option for a more verbose output.
.It Nm Ar cond clr | clear Ar COND
Clear (deassert) user-defined condition,
.Cm -usr/COND
@@ -139,7 +164,24 @@ Start service by name, with optional ID, e.g.,
.It Nm Ar stop Cm NAME[:ID]
Stop/Pause a running service by name
.It Nm Ar reload Cm NAME[:ID]
Reload service by name (SIGHUP or restart)
Reload service as if its configuration had changed. Internally,
.Nm finit
marks the named service as "dirty" and turns the state machine,
resulting in a SIGHUP or restart of (at least) the named service.
Any dependant services are also restarted.
.Pp
.Sy Note:
no .conf file is reloaded with this variant of the command. Essentially
it is the same as calling
.Cm restart .
Except for two things:
.Bl -enum -offset indent -compact
.It
if the service supports HUP, it's signaled instead of stop-started, and
.It
it allows restarting run/task in the same runlevel -- which is otherwise
restricted
.El
.It Nm Ar signal Cm NAME:[ID] S
Send signal S to service, by name.
.Cm S
+2 -2
View File
@@ -102,8 +102,8 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
service_forked(svc);
if (pid != svc->pid) {
_d("Forking service %s changed PID from %d to %d",
svc->cmd, svc->pid, pid);
_d("Forking service %s (cmd %s) changed PID from %d to %d",
svc_ident(svc, NULL, 0), svc->cmd, svc->pid, pid);
svc->pid = pid;
/* Complement log in service.c for non-forking services */
+9 -8
View File
@@ -23,7 +23,6 @@
#include "config.h"
#include <err.h>
#include <dirent.h>
#include <stdio.h>
#include <signal.h>
@@ -244,7 +243,7 @@ static float cgroup_cpuload(struct cg *cg)
snprintf(fn, sizeof(fn), "%s/cpu.stat", cg->cg_path);
fp = fopen(fn, "r");
if (!fp)
err(1, "Cannot open %s", fn);
ERR(72, "Cannot open %s", fn);
while (fgets(buf, sizeof(buf), fp)) {
uint64_t curr;
@@ -280,13 +279,13 @@ static struct cg *append(char *path)
if (access(fn, F_OK)) {
/* older kernels, 4.19, don't have summary cpu.stat in root */
if (strcmp(path, FINIT_CGPATH))
warn("not a cgroup path with cpu controller, %s", path);
WARN("not a cgroup path with cpu controller, %s", path);
return NULL;
}
cg = calloc(1, sizeof(struct cg));
if (!cg)
err(1, "failed allocating struct cg");
ERR(71, "failed allocating struct cg");
cg->cg_path = strdup(path);
if (list)
@@ -296,7 +295,7 @@ static struct cg *append(char *path)
item.key = cg->cg_path;
item.data = cg;
if (!hsearch(item, ENTER))
err(1, "failed adding to hash table");
ERR(70, "failed adding to hash table");
return cg;
}
@@ -434,7 +433,6 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
pid_comm(pid, comm, sizeof(comm));
if (pid_cmdline(pid, buf, sizeof(buf))) {
char proc[ttcols];
int len;
switch (mode) {
case 1:
@@ -456,6 +454,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
if (plain) {
strlcat(row, proc, rplen);
} else {
int len;
strlcat(row, CDIM, rlen);
strlcat(row, proc, rlen);
@@ -600,7 +600,6 @@ int show_cgtop(char *arg)
uev_t timer, input, sigint, sigterm, sigquit;
char path[512];
uev_ctx_t ctx;
int flags;
if (!arg)
arg = FINIT_CGPATH;
@@ -610,7 +609,7 @@ int show_cgtop(char *arg)
}
if (!hcreate(ttrows + 25))
err(1, "failed creating hash table");
ERR(70, "failed creating hash table");
sysinfo(&si);
total_ram = si.totalram * si.mem_unit;
@@ -619,6 +618,8 @@ int show_cgtop(char *arg)
uev_timer_init(&ctx, &timer, cgtop, arg, 1, ionce ? 0 : 1000);
if (!ionce && !plain) {
int flags;
atexit(cleanup);
ttraw();
hidecursor();
+14 -19
View File
@@ -21,13 +21,13 @@
* THE SOFTWARE.
*/
#include <err.h>
#include <errno.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "client.h"
#include "initctl.h"
static int sd = -1;
@@ -40,13 +40,13 @@ int client_connect(void)
sd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (-1 == sd) {
warn("Failed creating UNIX domain socket");
WARN("Failed creating UNIX domain socket");
return -1;
}
if (connect(sd, (struct sockaddr*)&sun, sizeof(sun)) == -1) {
if (errno != ENOENT)
warnx("Failed connecting to finit");
WARNX("Failed connecting to finit");
close(sd);
return -1;
}
@@ -72,22 +72,21 @@ int client_disconnect(void)
int client_send(struct init_request *rq, ssize_t len)
{
struct pollfd pfd = { 0 };
int sd, result = 255;
int result = 255;
int rc;
sd = client_connect();
if (-1 == sd)
if (client_connect() == -1)
return -1;
pfd.fd = sd;
pfd.events = POLLOUT;
if (poll(&pfd, 1, 2000) <= 0) {
warn("Timed out waiting for Finit, errno %d", errno);
WARN("Timed out waiting for Finit, errno %d", errno);
goto exit;
}
if (write(sd, rq, len) != len) {
warn("Failed communicating with Finit, errno %d", errno);
WARN("Failed communicating with Finit, errno %d", errno);
goto exit;
}
@@ -97,14 +96,14 @@ int client_send(struct init_request *rq, ssize_t len)
if (rc) {
if (errno == EINTR) /* shutdown/reboot */
goto exit;
warn("poll(), errno %d", errno);
WARN("poll(), errno %d", errno);
} else
warnx("Timed out waiting for reply from Finit.");
WARNX("Timed out waiting for reply from Finit.");
goto exit;
}
if (read(sd, rq, len) != len) {
warn("Failed reading reply from Finit, errno %d", errno);
WARN("Failed reading reply from Finit, errno %d", errno);
goto exit;
}
@@ -120,15 +119,13 @@ exit:
svc_t *client_svc_iterator(int first)
{
int sd = -1;
struct init_request rq = {
.magic = INIT_MAGIC,
.cmd = INIT_CMD_SVC_ITER,
};
static svc_t svc;
sd = client_connect();
if (sd == -1)
if (client_connect() == -1)
return NULL;
if (first)
@@ -147,7 +144,7 @@ svc_t *client_svc_iterator(int first)
return &svc;
error:
perror("Failed communicating with finit");
WARN("Failed communicating with finit, error %d", errno);
client_disconnect();
sd = -1;
@@ -161,10 +158,8 @@ svc_t *do_cmd(int cmd, const char *arg)
.cmd = cmd,
};
static svc_t svc;
int sd = -1;
sd = client_connect();
if (sd == -1)
if (client_connect() == -1)
return NULL;
strlcpy(rq.data, arg, sizeof(rq.data));
@@ -180,7 +175,7 @@ svc_t *do_cmd(int cmd, const char *arg)
return &svc;
error:
client_disconnect();
perror("Failed communicating with finit");
WARN("Failed communicating with finit, error %d", errno);
return NULL;
}
+2 -2
View File
@@ -454,12 +454,12 @@ void conf_parse_cond(svc_t *svc, char *cond)
ptr[i] = 0;
if (i >= sizeof(svc->cond)) {
logit(LOG_WARNING, "Too long event list in declaration of %s: %s", svc->cmd, ptr);
logit(LOG_WARNING, "Too long event list in declaration of %s: %s", svc_ident(svc, NULL, 0), ptr);
return;
}
if (!strncmp(ptr, "svc/", 4)) {
logit(LOG_ERR, "Unsupported cond syntax for %s: <%s", svc->cmd, ptr);
logit(LOG_ERR, "Unsupported cond syntax for %s: <%s", svc_ident(svc, NULL, 0), ptr);
return;
}
+78 -69
View File
@@ -23,7 +23,6 @@
#include "config.h"
#include <err.h>
#include <ftw.h>
#include <ctype.h>
#include <getopt.h>
@@ -39,6 +38,7 @@
# include <lite/lite.h>
#endif
#include "initctl.h"
#include "client.h"
#include "cond.h"
#include "serv.h"
@@ -154,12 +154,19 @@ static int toggle_debug(char *arg)
return client_send(&rq, sizeof(rq));
}
static int do_log(char *svc)
static int do_log(svc_t *svc, char *tail)
{
char *logfile = "/var/log/syslog";
const char *logfile = "/var/log/syslog";
pid_t pid;
char *nm;
if (!svc || !svc[0])
svc = "finit";
if (svc) {
nm = svc_ident(svc, NULL, 0);
pid = svc->pid;
} else {
nm = "finit";
pid = 1;
}
if (!fexist(logfile)) {
logfile = "/var/log/messages";
@@ -167,7 +174,20 @@ static int do_log(char *svc)
return 0; /* bail out, maybe in container */
}
return systemf("cat %s | grep %s | tail -10", logfile, svc);
return systemf("cat %s | grep '\\[%d\\]\\|%s' %s", logfile, pid, nm, tail);
}
static int show_log(char *arg)
{
svc_t *svc = NULL;
if (arg) {
svc = client_svc_find(arg);
if (!svc)
ERRX(69, "no such task or service(s): %s", arg);
}
return do_log(svc, "");
}
static int do_runlevel(char *arg)
@@ -229,20 +249,11 @@ static int do_startstop(int cmd, char *arg)
};
if (!arg || !arg[0])
errx(1, "missing argument to %s", (cmd == INIT_CMD_START_SVC
? "start"
: (cmd == INIT_CMD_STOP_SVC
? "stop"
: "restart")));
ERRX(2, "missing command argument");
strlcpy(rq.data, arg, sizeof(rq.data));
if (client_send(&rq, sizeof(rq))) {
fprintf(stderr, "No such task or service(s): %s\n\n", arg);
fprintf(stderr, "Usage: initctl %s <NAME>[:ID]\n",
cmd == INIT_CMD_START_SVC ? "start" :
(cmd == INIT_CMD_STOP_SVC ? "stop" : "restart"));
return 1;
}
if (client_send(&rq, sizeof(rq)))
ERRX(69, "no such task or service(s): %s", arg);
return do_svc(cmd, arg);
}
@@ -274,7 +285,7 @@ static int do_restart(char *arg)
}
if (retries == 0)
errx(1, "Failed stopping %s (restart)", arg);
ERRX(7, "failed stopping %s (restart)", arg);
return do_startstop(INIT_CMD_RESTART_SVC, arg);
}
@@ -298,27 +309,19 @@ int do_signal(int argc, char *argv[])
int signo;
if (argc != 2)
errx(1, "invalid number of arguments to signal");
ERRX(2, "invalid number of arguments to signal");
/* Validate service name */
strlcpy(rq.data, argv[0], sizeof(rq.data));
if (client_send(&rq, sizeof(rq))) {
fprintf(stderr, "No such task or service(s): %s\n\n", argv[0]);
goto show_usage;
}
if (client_send(&rq, sizeof(rq)))
ERRX(69, "no such task or service(s): %s", argv[0]);
/* Validate signal name (or number) */
signo = str2sig(argv[1]);
if (signo == -1) {
/* Not a signal name, is it an actual signal number? */
errno = 0;
signo = (int)strtol(argv[1], NULL, 10);
const char *errstr = NULL;
/* Was it a number? Was it a signo that finit recognizes? */
if (errno || !*(sig2str(signo))) {
fprintf(stderr, "Not a valid signal (or signo): %s\n", argv[1]);
goto show_usage;
}
signo = (int)strtonum(argv[1], 1, 31, &errstr);
if (errstr)
ERRX(65, "%s signal: %s", errstr, argv[1]);
}
/* Reuse runlevel for signal number. */
@@ -328,10 +331,6 @@ int do_signal(int argc, char *argv[])
strlcpy(rq.data, argv[0], sizeof(rq.data));
return client_send(&rq, sizeof(rq));
show_usage:
fprintf(stderr, "Usage: initctl signal <NAME>[:ID] <S>\n");
return 1;
}
static int dump_one_cond(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf)
@@ -384,56 +383,62 @@ static int do_cond_dump(char *arg)
}
if (nftw(_PATH_COND, dump_one_cond, 20, 0) == -1) {
warnx("Failed parsing %s", _PATH_COND);
WARNX("Failed parsing %s", _PATH_COND);
return 1;
}
return 0;
}
static int do_cond_act(char *arg, int op)
typedef enum { COND_CLR, COND_SET, COND_GET } condop_t;
static int do_cond_act(char *arg, condop_t op)
{
char oneshot[256];
char path[256];
size_t off;
if (arg && strncmp(arg, COND_USR, strlen(COND_USR)) == 0)
arg += strlen(COND_USR);
if (!arg || !arg[0])
errx(1, "Invalid condition (empty)");
if (strchr(arg, '/'))
errx(1, "Invalid condition (slashes)");
if (strchr(arg, '.'))
errx(1, "Invalid condition (periods)");
ERRX(2, "Invalid condition (empty)");
snprintf(oneshot, sizeof(oneshot), _PATH_CONDUSR "%s", arg);
/* allowed to read any condition, but not set/clr */
if (op != COND_GET) {
if (strchr(arg, '/'))
ERRX(2, "Invalid condition (slashes)");
if (strchr(arg, '.'))
ERRX(2, "Invalid condition (periods)");
}
if (strchr(arg, '/'))
snprintf(path, sizeof(path), _PATH_COND "%s", arg);
else
snprintf(path, sizeof(path), _PATH_CONDUSR "%s", arg);
off = strlen(_PATH_COND);
switch (op) {
case 2:
off = !fexist(oneshot);
case COND_GET:
off = !fexist(path);
if (verbose)
puts(off ? "off" : "on");
return off;
case 1:
if (symlink(_PATH_RECONF, oneshot) && errno != EEXIST)
err(1, "Failed asserting condition <%s>", &oneshot[off]);
case COND_SET:
if (symlink(_PATH_RECONF, path) && errno != EEXIST)
ERR(73, "Failed asserting condition <%s>", &path[off]);
break;
case 0:
if (erase(oneshot) && errno != ENOENT)
err(1, "Failed deasserting condition <%s>", &oneshot[off]);
break;
default:
errx(1, "Unsupported operation (%d)", op);
case COND_CLR:
if (erase(path) && errno != ENOENT)
ERR(73, "Failed deasserting condition <%s>", &path[off]);
break;
}
return 0;
}
static int do_cond_get(char *arg) { return do_cond_act(arg, 2); }
static int do_cond_set(char *arg) { return do_cond_act(arg, 1); }
static int do_cond_clr(char *arg) { return do_cond_act(arg, 0); }
static int do_cond_get(char *arg) { return do_cond_act(arg, COND_GET); }
static int do_cond_set(char *arg) { return do_cond_act(arg, COND_SET); }
static int do_cond_clr(char *arg) { return do_cond_act(arg, COND_CLR); }
static char *svc_cond(svc_t *svc, char *buf, size_t len)
{
@@ -811,7 +816,7 @@ static int show_status(char *arg)
svc = client_svc_find(arg);
if (!svc)
return 255;
ERRX(69, "no such task or service(s): %s", arg);
if (quiet) {
if (svc_is_runtask(svc))
@@ -864,7 +869,7 @@ static int show_status(char *arg)
no_cgroup:
printf("\n");
return do_log(svc->cmd);
return do_log(svc, "| tail -10");
}
col_widths();
@@ -974,13 +979,13 @@ static int usage(int rc)
" -b, --batch Batch mode, no screen size probing\n"
" -c, --create Create missing paths (and files) as needed\n"
" -f, --force Ignore missing files and arguments, never prompt\n"
" -h, --help This help text\n"
" -1, --once Only one lap in commands like 'top'\n"
" -p, --plain Use plain table headings, no ctrl chars\n"
" -q, --quiet Silent, only return status of command\n"
" -t, --no-heading Skip table headings\n"
" -v, --verbose Verbose output\n"
" -V, --version Show program version\n"
" -h, --help This help text\n"
"\n"
"Commands:\n"
" debug Toggle Finit (daemon) debug\n"
@@ -1009,13 +1014,12 @@ static int usage(int rc)
" disable <CONF> Disable .conf in %s\n", ena);
if (has_rcsd)
fprintf(stderr,
" reload Reload *.conf in " FINIT_RCSD " (activate changes)\n");
" reload Reload *.conf in " FINIT_RCSD " (activate changes)\n");
else
fprintf(stderr,
" reload Reload " FINIT_CONF " (activate changes)\n");
fprintf(stderr,
// " reload <NAME>[:ID] Reload (SIGHUP) service by name\n"
"\n"
" cond set <COND> Set (assert) user-defined condition +usr/COND\n"
" cond get <COND> Get status of user-defined condition, see $? and -v\n"
@@ -1026,7 +1030,9 @@ static int usage(int rc)
" log [NAME] Show ten last Finit, or NAME, messages from syslog\n"
" start <NAME>[:ID] Start service by name, with optional ID\n"
" stop <NAME>[:ID] Stop/Pause a running service by name\n"
" reload <NAME>[:ID] Reload service by name (SIGHUP or restart)\n"
" reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)\n"
" This allows restart of run/tasks that have already run\n"
" Note: Finit .conf file(s) are *not* reloaded!\n"
" restart <NAME>[:ID] Restart (stop/start) service by name\n"
" signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID\n"
" ident [NAME] Show matching identities for NAME, or all\n"
@@ -1108,7 +1114,7 @@ static int cmd_parse(int argc, char *argv[], struct cmd *command)
}
if (argv[0] && strlen(argv[0]) > 0)
errx(1, "No such command. See 'initctl help' for an overview of available commands.");
ERRX(3, "No such command. See 'initctl help' for an overview of available commands.");
return command[0].cb(NULL); /* default cmd */
}
@@ -1160,7 +1166,7 @@ int main(int argc, char *argv[])
{ "cond", cond, NULL, NULL, NULL },
{ "log", NULL, do_log, NULL, NULL },
{ "log", NULL, show_log, NULL, NULL },
{ "start", NULL, do_start, NULL, NULL },
{ "stop", NULL, do_stop, NULL, NULL },
{ "restart", NULL, do_restart, NULL, NULL },
@@ -1245,6 +1251,9 @@ void logit(int prio, const char *fmt, ...)
{
va_list ap;
if (quiet)
return;
va_start(ap, fmt);
if (prio <= LOG_ERR)
verrx(1, fmt, ap);
+8
View File
@@ -24,6 +24,8 @@
#ifndef FINIT_INITCTL_H_
#define FINIT_INITCTL_H_
#include <err.h>
#include "finit.h"
#include "util.h"
@@ -33,6 +35,12 @@ extern int ionce; /* initctl -1 */
extern int heading; /* initctl -t */
extern int verbose; /* initctl -v */
extern int plain; /* initctl -p */
extern int quiet; /* initctl -q */
#define ERR(rc, fmt, args...) do { if (!quiet) err(rc, fmt, ##args); else exit(rc); } while (0)
#define ERRX(rc, fmt, args...) do { if (!quiet) errx(rc, fmt, ##args); else exit(rc); } while (0)
#define WARN(fmt, args...) do { if (!quiet) warn(fmt, ##args); } while (0)
#define WARNX(fmt, args...) do { if (!quiet) warnx(fmt, ##args); } while (0)
extern void print_header(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+28 -29
View File
@@ -23,7 +23,6 @@
#include "config.h"
#include <err.h>
#include <fcntl.h> /* Definition of AT_* constants */
#include <glob.h>
#include <stdio.h>
@@ -233,7 +232,7 @@ int serv_enable(char *arg)
int ena;
if (!arg || !arg[0]) {
warnx("missing argument to enable, may be one of:");
WARNX("missing argument to enable, may be one of:");
return serv_list("available");
}
@@ -243,18 +242,18 @@ int serv_enable(char *arg)
}
if (chdir(FINIT_RCSD))
err(1, "failed cd %s", FINIT_RCSD);
ERR(72, "failed cd %s", FINIT_RCSD);
if (icreate && mkdir("enabled", 0755) && EEXIST != errno)
err(1, "failed creating %s/enabled directory", FINIT_RCSD);
ERR(73, "failed creating %s/enabled directory", FINIT_RCSD);
ena = !chdir("enabled"); /* System *may* have enabled/ dir. */
snprintf(path, sizeof(path), "%savailable/%s", ena ? "../" : "", arg);
if (!fexist(path))
errx(1, "cannot find %s", conf(path, sizeof(path), arg, 0));
ERRX(72, "cannot find %s", conf(path, sizeof(path), arg, 0));
if (fexist(arg))
errx(1, "%s already enabled", arg);
ERRX(1, "%s already enabled", arg);
return symlink(path, arg) != 0;
}
@@ -265,7 +264,7 @@ int do_disable(char *arg, int check)
char corr[40];
if (!arg || !arg[0]) {
warnx("missing argument to disable, may be one of:");
WARNX("missing argument to disable, may be one of:");
return serv_list("enabled");
}
@@ -275,15 +274,15 @@ int do_disable(char *arg, int check)
}
if (chdir(FINIT_RCSD))
err(1, "failed cd %s", FINIT_RCSD);
ERR(72, "failed cd %s", FINIT_RCSD);
if (chdir("enabled")) /* System *may* have enabled/ dir. */
dbg("Failed changing to %s/enabled/: %s", FINIT_RCSD, strerror(errno));
if (check && stat(arg, &st))
errx(1, "%s not (an) enabled (service).", arg);
ERRX(6, "%s not (an) enabled (service).", arg);
if (check && (st.st_mode & S_IFMT) == S_IFLNK)
errx(1, "cannot disable %s, not a symlink.", arg);
ERRX(1, "cannot disable %s, not a symlink.", arg);
return remove(arg) != 0;
}
@@ -299,16 +298,16 @@ int serv_touch(char *arg)
char *fn;
if (!arg || !arg[0]) {
warnx("missing argument to touch, may be one of:");
WARNX("missing argument to touch, may be one of:");
return serv_list("enabled");
}
fn = conf(path, sizeof(path), arg, 0);
if (!fexist(fn)) {
if (!strstr(arg, "finit.conf"))
errx(1, "%s not available.", arg);
ERRX(72, "%s not available.", arg);
if (is_builtin(arg))
errx(1, "%s is a built-in service.", arg);
ERRX(4, "%s is a built-in service.", arg);
strlcpy(path, FINIT_CONF, sizeof(path));
fn = path;
@@ -316,7 +315,7 @@ int serv_touch(char *arg)
/* libite:touch() follows symlinks */
if (utimensat(AT_FDCWD, fn, NULL, AT_SYMLINK_NOFOLLOW))
err(1, "failed marking %s for reload", fn);
ERR(71, "failed marking %s for reload", fn);
return 0;
}
@@ -329,9 +328,9 @@ int serv_show(char *arg)
fn = conf(path, sizeof(path), arg, 0);
if (!fexist(fn)) {
if (is_builtin(arg))
errx(1, "%s is a built-in service.", arg);
ERRX(4, "%s is a built-in service.", arg);
warnx("Cannot find %s", arg);
WARNX("Cannot find %s", arg);
return 1;
}
@@ -366,10 +365,10 @@ static int do_edit(char *arg, int creat)
fn = conf(path, sizeof(path), arg, creat);
if (!fexist(fn)) {
if (is_builtin(arg))
errx(1, "%s is a built-in service.", arg);
ERRX(4, "%s is a built-in service.", arg);
if (!creat) {
warnx("Cannot find %s, use -c flag, create command, or select one of:", arg);
WARNX("Cannot find %s, use -c flag, create command, or select one of:", arg);
return serv_list(NULL);
}
@@ -378,7 +377,7 @@ static int do_edit(char *arg, int creat)
copyfile(SAMPLE_CONF, fn, 0, 0);
#endif
} else if (creat)
warnx("the file %s already exists, falling back to edit.", fn);
WARNX("the file %s already exists, falling back to edit.", fn);
for (size_t i = 0; i < NELEMS(editor); i++) {
if (systemf("%s %s 2>/dev/null", editor[i], path))
@@ -407,10 +406,10 @@ int serv_creat(char *arg)
FILE *fp;
if (!arg || !arg[0])
errx(1, "missing argument to create");
ERRX(2, "missing argument to create");
if (is_builtin(arg))
errx(1, "%s is a built-in service.", arg);
ERRX(4, "%s is a built-in service.", arg);
/* Input from a pipe or a proper TTY? */
if (isatty(STDIN_FILENO))
@@ -419,16 +418,16 @@ int serv_creat(char *arg)
/* Open fn for writing from pipe */
fn = conf(buf, sizeof(buf), arg, 1);
if (!fn)
err(1, "failed creating conf %s", arg);
ERR(73, "failed creating conf %s", arg);
if (!icreate && fexist(fn)) {
warnx("%s already exists, skipping (use -c to override)", fn);
WARNX("%s already exists, skipping (use -c to override)", fn);
fn = "/dev/null";
}
fp = fopen(fn, "w");
if (!fp)
err(1, "failed opening %s for writing", fn);
ERR(73, "failed opening %s for writing", fn);
while (fgets(buf, sizeof(buf), stdin))
fputs(buf, fp);
@@ -442,24 +441,24 @@ int serv_delete(char *arg)
char *fn;
if (!arg || !arg[0]) {
warnx("missing argument to delete, may be one of:");
WARNX("missing argument to delete, may be one of:");
return serv_list("available");
}
fn = conf(buf, sizeof(buf), arg, 0);
if (!fn) {
if (is_builtin(arg))
errx(1, "%s is a built-in service.", arg);
errx(1, FINIT_RCSD " missing on system.");
ERRX(4, "%s is a built-in service.", arg);
ERRX(72, FINIT_RCSD " missing on system.");
}
if (!fexist(fn))
warnx("cannot find %s", fn);
WARNX("cannot find %s", fn);
if (iforce || yorn("Remove file and symlink(s) to %s (y/N)? ", fn)) {
do_disable(arg, 0);
if (remove(fn))
err(1, "Failed removing %s", fn);
ERR(1, "Failed removing %s", fn);
}
return 0;
+23 -20
View File
@@ -198,9 +198,10 @@ static int lredirect(svc_t *svc)
pid = fork();
if (pid == 0) {
int fds;
char *tag = basename(svc->cmd);
char *prio = "daemon.info";
char buf[MAX_IDENT_LEN];
char *tag;
int fds;
sched_yield();
@@ -213,6 +214,9 @@ static int lredirect(svc_t *svc)
/* Reset signals */
sig_unblock();
/* Default syslog identity name[:id] */
tag = svc_ident(svc, buf, sizeof(buf));
if (!whichp(_PATH_LOGIT)) {
logit(LOG_INFO, _PATH_LOGIT " missing, using syslog for %s instead", svc->name);
fallback_logger(tag, prio);
@@ -416,20 +420,19 @@ static pid_t service_fork(svc_t *svc)
/* Set configured limits */
for (int i = 0; i < RLIMIT_NLIMITS; i++) {
if (setrlimit(i, &svc->rlimit[i]) == -1)
logit(LOG_WARNING,
"%s: rlimit: Failed setting %s",
svc->cmd, rlim2str(i));
logit(LOG_WARNING, "%s: rlimit: failed setting %s",
svc_ident(svc, NULL, 0), rlim2str(i));
}
/* Set desired user+group */
if (gid >= 0) {
if (setgid(gid))
_pe("%s: failed setgid(%d)", svc->cmd, gid);
_pe("%s: failed setgid(%d)", svc_ident(svc, NULL, 0), gid);
}
if (uid >= 0) {
if (setuid(uid))
_pe("%s: failed setuid(%d)", svc->cmd, uid);
_pe("%s: failed setuid(%d)", svc_ident(svc, NULL, 0), uid);
/* Set default path for regular users */
if (uid > 0)
@@ -438,7 +441,7 @@ static pid_t service_fork(svc_t *svc)
setenv("HOME", home, 1);
if (chdir(home)) {
if (chdir("/"))
_pe("%s: failed chdir(%s) and chdir(/)", svc->cmd, home);
_pe("%s: failed chdir(%s) and chdir(/)", svc_ident(svc, NULL, 0), home);
}
}
}
@@ -475,14 +478,14 @@ static int service_start(svc_t *svc)
/* Don't try and start service if it doesn't exist. */
if (!whichp(svc->cmd)) {
logit(LOG_WARNING, "%s: missing or not in $PATH", svc->cmd);
logit(LOG_WARNING, "%s: missing %s or not in $PATH", svc_ident(svc, NULL, 0), svc->cmd);
svc_missing(svc);
return 1;
}
/* Unlike systemd we do not allow starting service if env is missing, unless - */
if (!svc_checkenv(svc)) {
logit(LOG_WARNING, "%s: missing env file %s", svc->cmd, svc->env);
logit(LOG_WARNING, "%s: missing %s env file %s", svc_ident(svc, NULL, 0), svc->cmd, svc->env);
svc_missing(svc);
return 1;
}
@@ -535,7 +538,7 @@ static int service_start(svc_t *svc)
int rc;
if ((rc = wordexp(svc->cmd, &we, 0))) {
_e("%s: failed wordexp(%s): %d", svc->cmd, svc->cmd, rc);
_e("%s: failed wordexp(%s): %d", svc_ident(svc, NULL, 0), svc->cmd, rc);
nomem:
wordfree(&we);
_exit(1);
@@ -563,19 +566,19 @@ static int service_start(svc_t *svc)
strlcat(str, arg, sizeof(str));
if ((rc = wordexp(str, &we, WRDE_APPEND))) {
_e("%s: failed wordexp(%s): %d", svc->cmd, str, rc);
_e("%s: failed wordexp(%s): %d", svc_ident(svc, NULL, 0), str, rc);
goto nomem;
}
}
if (we.we_wordc > MAX_NUM_SVC_ARGS) {
logit(LOG_ERR, "%s: too man args after expansion.", svc->cmd);
logit(LOG_ERR, "%s: too many args to %s after expansion.", svc_ident(svc, NULL, 0), svc->cmd);
goto nomem;
}
for (i = 0; i < we.we_wordc; i++) {
if (strlen(we.we_wordv[i]) >= sizeof(svc->args[i])) {
logit(LOG_ERR, "%s: expanded arg. '%s' too long", svc->cmd, we.we_wordv[i]);
logit(LOG_ERR, "%s: expanded %s arg. '%s' too long", svc_ident(svc, NULL, 0), svc->cmd, we.we_wordv[i]);
rc = WRDE_NOSPACE;
goto nomem;
}
@@ -684,7 +687,7 @@ static void service_kill(svc_t *svc)
if (svc->pid <= 1) {
/* Avoid killing ourselves or all processes ... */
_d("%s: Aborting SIGKILL, already terminated.", svc->cmd);
_d("%s: Aborting SIGKILL, already terminated.", svc_ident(svc, NULL, 0));
return;
}
@@ -714,7 +717,7 @@ static void service_cleanup(svc_t *svc)
fn = pid_file(svc);
if (fn && remove(fn) && errno != ENOENT)
logit(LOG_CRIT, "Failed removing service %s pidfile %s",
basename(svc->cmd), fn);
svc_ident(svc, NULL, 0), fn);
/* No longer running, update books. */
if (svc_is_tty(svc) && svc->pid > 1)
@@ -857,7 +860,7 @@ static int service_restart(svc_t *svc)
return 1;
if (svc->pid <= 1) {
_d("Bad PID %d for %s, SIGHUP", svc->pid, svc->cmd);
_d("%s: bad PID %d for %s, SIGHUP", svc_ident(svc, NULL, 0), svc->pid, svc->cmd);
svc->start_time = svc->pid = 0;
return 1;
}
@@ -960,7 +963,7 @@ static void parse_env(svc_t *svc, char *env)
return;
if (strlen(env) >= sizeof(svc->env)) {
_e("%s: env file is too long (>%zu chars)", svc->cmd, sizeof(svc->env));
_e("%s: env file is too long (>%zu chars)", svc_ident(svc, NULL, 0), sizeof(svc->env));
return;
}
@@ -984,7 +987,7 @@ static void parse_cgroup(svc_t *svc, char *cgroup)
}
if (strlen(ptr) >= sizeof(svc->cgroup)) {
_e("%s: cgroup settings too long (>%zu chars)", svc->cmd, sizeof(svc->cgroup));
_e("%s: cgroup settings too long (>%zu chars)", svc_ident(svc, NULL, 0), sizeof(svc->cgroup));
return;
}
@@ -1009,7 +1012,7 @@ static void parse_killdelay(svc_t *svc, char *delay)
sec = strtonum(delay, 1, 60, &errstr);
if (errstr) {
_e("%s: killdelay %s is %s (1-60)", svc->cmd, delay, errstr);
_e("%s: killdelay %s is %s (1-60)", svc_ident(svc, NULL, 0), delay, errstr);
return;
}
+2 -2
View File
@@ -187,7 +187,7 @@ restart:
*/
svc = svc_stop_completed();
if (svc) {
_d("Waiting to collect %s(%d) ...", svc->cmd, svc->pid);
_d("Waiting to collect %s, cmd %s(%d) ...", svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
break;
}
@@ -240,7 +240,7 @@ restart:
*/
svc = svc_stop_completed();
if (svc) {
_d("Waiting to collect %s(%d) ...", svc->cmd, svc->pid);
_d("Waiting to collect %s, cmd %s(%d) ...", svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
break;
}
-1
View File
@@ -24,7 +24,6 @@
#include "config.h" /* Generated by configure script */
#include <err.h>
#include <ctype.h> /* isdigit() */
#include <time.h>
#include <signal.h>