mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f483a8aeaa | ||
|
|
e3e220ce8e | ||
|
|
fc653e4293 | ||
|
|
94d55cb7dd | ||
|
|
0e84ecf143 | ||
|
|
0e93dfd640 | ||
|
|
4dff8237f1 | ||
|
|
35400f2a8b | ||
|
|
9a76f0862c | ||
|
|
fb8a7caa99 | ||
|
|
f8bed5c7af | ||
|
|
da6fa482e7 | ||
|
|
fdf8e48c99 | ||
|
|
195155a7f5 | ||
|
|
6934ba4dbc | ||
|
|
fdbd25c1b5 | ||
|
|
467f1cca81 | ||
|
|
d6fdf4a806 | ||
|
|
4be9d97e61 | ||
|
|
021d011493 | ||
|
|
e988d38f71 | ||
|
|
8690fc732b |
+16
-2
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user