waits-for = (service name)
termsignal = HUP | INT | QUIT | USR1 | USR2
-command = (external script or executable and arguments)
+command = (external script or executable, and arguments)
For a 'process' service, this is the process to run.
- For a 'scripted' service, this process is run both to start the service
- (with the command-line argument "start" appended) and to stop the
- service (with "stop").
+ For a 'scripted' service, this command is run to start the service.
+
+stop-command = (external script or executable, and arguments)
+ For a 'scripted' service, this command is run to stop the service.
onstart = (internal commands)
- release_console - stop performing output to the console (usually used
- when login prompt is spawned)
rw_ready - try again to open any logs, control socket etc that could not
be opened previously due to a read-only filesystem.
an alternate signal is specified using the "termsignal" setting, that
signal will be sent instead; otherwise, no signal will be sent, and the
process must be killed by external means).
+
+runs-on-console = yes | no | true | false
+ If true, the service runs on the console; its input and output are
+ directed to the console (actually, to the terminal on which Dinit is
+ running) and Dinit's own output will be suppressed during this time.
+ Control signals (^C) may be used to control a service running on the
+ console.
+
+ This is useful to allow a "login" master service to prevent Dinit output
+ once terminal sessions are spawned, or to make fsck display its progress
+ on the terminal (and be interruptible).
+
+ Only one service can run on the console at a time (services will queue
+ in order to gain access to the console).
+
+ For scripted services, only the start command runs on the console.
+ Process services and internal services take the console for the entire
+ time that they are active (and cannot release it).
+
string onstart_cmds = read_setting_value(i, end, &indices);
for (auto indexpair : indices) {
string onstart_cmd = onstart_cmds.substr(indexpair.first, indexpair.second - indexpair.first);
- if (onstart_cmd == "release_console") {
- onstart_flags.release_console = true;
- }
- else if (onstart_cmd == "rw_ready") {
+ if (onstart_cmd == "rw_ready") {
onstart_flags.rw_ready = true;
}
else {
return all_deps_started;
}
-void ServiceRecord::allDepsStarted(bool hasConsole) noexcept
+void ServiceRecord::allDepsStarted(bool has_console) noexcept
{
- if (onstart_flags.runs_on_console && ! hasConsole) {
+ if (onstart_flags.runs_on_console && ! has_console) {
waiting_for_deps = true;
queueForConsole();
return;
waiting_for_deps = false;
+ if (has_console) log_to_console = false;
+
if (service_type == ServiceType::PROCESS) {
bool start_success = start_ps_process();
if (start_success) {
service_state = ServiceState::STARTED;
notifyListeners(ServiceEvent::STARTED);
- if (onstart_flags.release_console) {
- log_to_console = false;
- }
-
if (onstart_flags.rw_ready) {
open_control_socket(ev_default_loop(EVFLAG_AUTO));
}
void ServiceRecord::releaseConsole() noexcept
{
+ log_to_console = true;
if (next_for_console != nullptr) {
next_for_console->acquiredConsole();
}
*/
struct OnstartFlags {
- bool release_console : 1;
bool rw_ready : 1;
// Not actually "onstart" commands:
bool no_sigterm : 1; // do not send SIGTERM
bool runs_on_console : 1; // run "in the foreground"
- OnstartFlags() noexcept : release_console(false), rw_ready(false),
+ OnstartFlags() noexcept : rw_ready(false),
no_sigterm(false), runs_on_console(false)
{
}