mirror of https://github.com/nocturn9x/nimd.git
Added more entries to gitignore
This commit is contained in:
parent
539035f3a5
commit
3f3403170f
|
@ -11,3 +11,4 @@ packervm
|
||||||
test
|
test
|
||||||
initramfs-linux.img
|
initramfs-linux.img
|
||||||
vmlinuz-linux
|
vmlinuz-linux
|
||||||
|
debian*
|
||||||
|
|
|
@ -350,9 +350,44 @@ proc createSymlinks*(logger: Logger) =
|
||||||
createDir(sym.dest.splitPath().head)
|
createDir(sym.dest.splitPath().head)
|
||||||
createSymlink(sym.source, sym.dest)
|
createSymlink(sym.source, sym.dest)
|
||||||
except:
|
except:
|
||||||
logger.warning(&"Failed to create symbolic link from {sym.dest} to {sym.source}: {getCurrentExceptionMsg()}")
|
logger.error(&"Failed to create symbolic link from {sym.dest} to {sym.source}: {getCurrentExceptionMsg()}")
|
||||||
|
|
||||||
|
|
||||||
proc createDirectories*(logger: Logger) =
|
proc createDirectories*(logger: Logger) =
|
||||||
## Creates standard directories that
|
## Creates standard directories that
|
||||||
## Linux software expects to be present.
|
## Linux software expects to be present.
|
||||||
|
## Note that this has to run after the
|
||||||
|
## filesystem has been initialized.
|
||||||
|
## If a chmod binary is found, it is used
|
||||||
|
## to set directory permissions as specified
|
||||||
|
## in their config. Note that the entire path
|
||||||
|
## of the directory is created if it does not
|
||||||
|
## exist yet
|
||||||
|
var hasChmod = false
|
||||||
|
try:
|
||||||
|
if findExe("chmod").isEmptyOrWhitespace():
|
||||||
|
logger.warning("Could not find chmod binary, directory permissions will default to OS configuration")
|
||||||
|
hasChmod = true
|
||||||
|
except:
|
||||||
|
logger.error(&"Failed to search for chmod binary: {getCurrentExceptionMsg()}")
|
||||||
|
for dir in directories:
|
||||||
|
try:
|
||||||
|
if exists(dir.path):
|
||||||
|
if dirExists(dir.path):
|
||||||
|
logger.warning(&"Creation of directory {dir.path} skipped: directory already exists")
|
||||||
|
elif fileExists(dir.path):
|
||||||
|
logger.warning(&"Creation of directory {dir.path} skipped: path is a file")
|
||||||
|
elif symlinkExists(dir.path):
|
||||||
|
logger.warning(&"Creation of directory {dir.path} skipped: path is a symlink to {expandSymlink(dir.path)}")
|
||||||
|
else:
|
||||||
|
# Catch-all
|
||||||
|
logger.warning(&"Creation of directory {dir.path} skipped: destination already exists")
|
||||||
|
else:
|
||||||
|
createDir(dir.path)
|
||||||
|
logger.debug(&"Created new directory at {dir.path}")
|
||||||
|
if hasChmod:
|
||||||
|
logger.debug(&"Setting permissions to {dir.permissions} for {dir.path}")
|
||||||
|
if (let code = execShellCmd(&"chmod -R {dir.permissions} {dir.path}"); code) != 0:
|
||||||
|
logger.warning(&"Command 'chmod -R {dir.permissions}' exited non-zero status code {code}")
|
||||||
|
except:
|
||||||
|
logger.error(&"Failed to create directory at {dir.path}: {getCurrentExceptionMsg()}")
|
||||||
|
|
|
@ -17,10 +17,13 @@ import tables
|
||||||
import osproc
|
import osproc
|
||||||
import posix
|
import posix
|
||||||
import shlex
|
import shlex
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
proc strsignal(sig: cint): cstring {.header: "string.h", importc.}
|
||||||
|
|
||||||
|
|
||||||
import ../util/logging
|
import ../util/logging
|
||||||
import ../util/misc
|
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -31,6 +34,9 @@ type
|
||||||
## Enumerates all service
|
## Enumerates all service
|
||||||
## types
|
## types
|
||||||
Oneshot, Simple
|
Oneshot, Simple
|
||||||
|
RestartKind* = enum
|
||||||
|
## Enum of possible restart modes
|
||||||
|
Always, OnFailure, Never
|
||||||
Service* = ref object of RootObj
|
Service* = ref object of RootObj
|
||||||
## A service object
|
## A service object
|
||||||
name: string
|
name: string
|
||||||
|
@ -40,14 +46,14 @@ type
|
||||||
runlevel: RunLevel
|
runlevel: RunLevel
|
||||||
exec: string
|
exec: string
|
||||||
supervised: bool
|
supervised: bool
|
||||||
restartOnFailure: bool
|
restart: RestartKind
|
||||||
restartDelay: int
|
restartDelay: int
|
||||||
|
|
||||||
|
|
||||||
proc newService*(name, description: string, kind: ServiceKind, workDir: string, runlevel: RunLevel, exec: string, supervised, restartOnFailure: bool, restartDelay: int): Service =
|
proc newService*(name, description: string, kind: ServiceKind, workDir: string, runlevel: RunLevel, exec: string, supervised: bool, restart: RestartKind, restartDelay: int): Service =
|
||||||
## Creates a new service object
|
## Creates a new service object
|
||||||
result = Service(name: name, description: description, kind: kind, workDir: workDir, runLevel: runLevel,
|
result = Service(name: name, description: description, kind: kind, workDir: workDir, runLevel: runLevel,
|
||||||
exec: exec, supervised: supervised, restartOnFailure: restartOnFailure, restartDelay: restartDelay)
|
exec: exec, supervised: supervised, restart: restart, restartDelay: restartDelay)
|
||||||
|
|
||||||
|
|
||||||
var services: seq[Service] = @[]
|
var services: seq[Service] = @[]
|
||||||
|
@ -114,25 +120,42 @@ proc supervisorWorker(logger: Logger, service: Service, pid: int) =
|
||||||
sig = WTERMSIG(status)
|
sig = WTERMSIG(status)
|
||||||
else:
|
else:
|
||||||
sig = -1
|
sig = -1
|
||||||
if sig > 0 and service.restartOnFailure:
|
case service.restart:
|
||||||
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
of Never:
|
||||||
removeManagedProcess(pid)
|
logger.info(&"Service '{service.name}' ({returnCode}) has exited, shutting down controlling process")
|
||||||
sleepSeconds(service.restartDelay)
|
|
||||||
var split = shlex(service.exec)
|
|
||||||
if split.error:
|
|
||||||
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
|
||||||
break
|
break
|
||||||
var arguments = split.words
|
of Always:
|
||||||
let progName = arguments[0]
|
if sig > 0:
|
||||||
arguments = arguments[1..^1]
|
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
||||||
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
elif sig == 0:
|
||||||
pid = process.processID()
|
logger.info(&"Service '{service.name}' has exited gracefully, sleeping {service.restartDelay} seconds before restarting it")
|
||||||
elif sig > 0:
|
else:
|
||||||
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), shutting down controlling process")
|
logger.info(&"Service '{service.name}' has exited, sleeping {service.restartDelay} seconds before restarting it")
|
||||||
break
|
removeManagedProcess(pid)
|
||||||
else:
|
sleep(service.restartDelay * 1000)
|
||||||
logger.info(&"Service '{service.name}' ({returnCode}) has exited, shutting down controlling process")
|
var split = shlex(service.exec)
|
||||||
break
|
if split.error:
|
||||||
|
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
||||||
|
break
|
||||||
|
var arguments = split.words
|
||||||
|
let progName = arguments[0]
|
||||||
|
arguments = arguments[1..^1]
|
||||||
|
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||||
|
pid = process.processID()
|
||||||
|
of OnFailure:
|
||||||
|
if sig > 0:
|
||||||
|
logger.info(&"Service '{service.name}' ({returnCode}) has crashed (terminated by signal {sig}: {strsignal(cint(sig))}), sleeping {service.restartDelay} seconds before restarting it")
|
||||||
|
removeManagedProcess(pid)
|
||||||
|
sleep(service.restartDelay * 1000)
|
||||||
|
var split = shlex(service.exec)
|
||||||
|
if split.error:
|
||||||
|
logger.error(&"Error while restarting service '{service.name}': invalid exec syntax")
|
||||||
|
break
|
||||||
|
var arguments = split.words
|
||||||
|
let progName = arguments[0]
|
||||||
|
arguments = arguments[1..^1]
|
||||||
|
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||||
|
pid = process.processID()
|
||||||
if process != nil:
|
if process != nil:
|
||||||
process.close()
|
process.close()
|
||||||
|
|
||||||
|
@ -140,7 +163,8 @@ proc supervisorWorker(logger: Logger, service: Service, pid: int) =
|
||||||
proc startService(logger: Logger, service: Service) =
|
proc startService(logger: Logger, service: Service) =
|
||||||
## Starts a single service (this is called by
|
## Starts a single service (this is called by
|
||||||
## startServices below until all services have
|
## startServices below until all services have
|
||||||
## been started)
|
## been started). This function is supposed to
|
||||||
|
## be called from a forked process!
|
||||||
var process: Process
|
var process: Process
|
||||||
try:
|
try:
|
||||||
var split = shlex(service.exec)
|
var split = shlex(service.exec)
|
||||||
|
@ -152,7 +176,9 @@ proc startService(logger: Logger, service: Service) =
|
||||||
arguments = arguments[1..^1]
|
arguments = arguments[1..^1]
|
||||||
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
process = startProcess(progName, workingDir=service.workDir, args=arguments)
|
||||||
if service.supervised:
|
if service.supervised:
|
||||||
supervisorWorker(logger, service, process.processID)
|
var pid = posix.fork()
|
||||||
|
if pid == 0:
|
||||||
|
supervisorWorker(logger, service, process.processID)
|
||||||
# If the service is unsupervised we just exit
|
# If the service is unsupervised we just exit
|
||||||
except:
|
except:
|
||||||
logger.error(&"Error while starting service {service.name}: {getCurrentExceptionMsg()}")
|
logger.error(&"Error while starting service {service.name}: {getCurrentExceptionMsg()}")
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import os
|
import os
|
||||||
|
import osproc
|
||||||
import posix
|
import posix
|
||||||
import glob
|
import glob
|
||||||
import strutils
|
import strutils
|
||||||
|
@ -20,6 +21,7 @@ import times
|
||||||
|
|
||||||
|
|
||||||
import ../util/logging
|
import ../util/logging
|
||||||
|
import services
|
||||||
|
|
||||||
|
|
||||||
type ShutdownHandler* = ref object
|
type ShutdownHandler* = ref object
|
||||||
|
@ -79,17 +81,15 @@ proc nimDExit*(logger: Logger, code: int, emerg: bool = true) =
|
||||||
## as cleanly as possible. When emerg equals true, it will
|
## as cleanly as possible. When emerg equals true, it will
|
||||||
## try to spawn a root shell and exit
|
## try to spawn a root shell and exit
|
||||||
if emerg:
|
if emerg:
|
||||||
var status: cint
|
|
||||||
# We're in emergency mode: do not crash the kernel, spawn a shell and exit
|
# We're in emergency mode: do not crash the kernel, spawn a shell and exit
|
||||||
logger.fatal("NimD has entered emergency mode and cannot continue. You will be now (hopefully) dropped in a root shell: you're on your own. May the force be with you")
|
logger.fatal("NimD has entered emergency mode and cannot continue. You will be now (hopefully) dropped in a root shell: you're on your own. May the force be with you")
|
||||||
logger.info("Terminating child processes with SIGKILL")
|
logger.info("Terminating child processes with SIGKILL")
|
||||||
discard posix.kill(SIGKILL, -1)
|
discard execCmd("/bin/sh") # TODO: Is this fine? maybe use execProcess
|
||||||
discard posix.waitPid(-1, status, 0)
|
discard posix.kill(-1, SIGKILL)
|
||||||
discard execShellCmd("/bin/sh") # TODO: Is this fine? maybe use execProcess
|
|
||||||
quit(-1)
|
quit(-1)
|
||||||
logger.warning("The system is shutting down")
|
logger.warning("The system is shutting down")
|
||||||
logger.info("Processing shutdown runlevel")
|
logger.info("Processing shutdown runlevel")
|
||||||
# TODO
|
startServices(logger, Shutdown)
|
||||||
logger.info("Running shutdown handlers")
|
logger.info("Running shutdown handlers")
|
||||||
try:
|
try:
|
||||||
for handler in shutdownHandlers:
|
for handler in shutdownHandlers:
|
||||||
|
@ -99,13 +99,13 @@ proc nimDExit*(logger: Logger, code: int, emerg: bool = true) =
|
||||||
# Note: continues calling handlers!
|
# Note: continues calling handlers!
|
||||||
logger.info("Terminating child processes with SIGTERM")
|
logger.info("Terminating child processes with SIGTERM")
|
||||||
logger.debug(&"Waiting up to {sigTermDelay} seconds for the kernel to deliver signals")
|
logger.debug(&"Waiting up to {sigTermDelay} seconds for the kernel to deliver signals")
|
||||||
discard posix.kill(SIGTERM, -1) # The kernel handles this for us asynchronously
|
discard posix.kill(-1, SIGTERM) # The kernel handles this for us asynchronously
|
||||||
var t = cpuTime()
|
var t = cpuTime()
|
||||||
# We wait some time for the signals to propagate
|
# We wait some time for the signals to propagate
|
||||||
while anyUserlandProcessLeft() or cpuTime() - t >= sigTermDelay:
|
while anyUserlandProcessLeft() or cpuTime() - t >= sigTermDelay:
|
||||||
sleep(int(0.25 * 1000))
|
sleep(int(0.25 * 1000))
|
||||||
if anyUserlandProcessLeft():
|
if anyUserlandProcessLeft():
|
||||||
logger.info("Terminating child processes with SIGKILL")
|
logger.info("Terminating child processes with SIGKILL")
|
||||||
discard posix.kill(SIGKILL, -1)
|
discard posix.kill(-1, SIGKILL)
|
||||||
logger.warning("Shutdown procedure complete, sending final termination signal")
|
logger.warning("Shutdown procedure complete, sending final termination signal")
|
||||||
quit(code)
|
quit(code)
|
||||||
|
|
103
src/main.nim
103
src/main.nim
|
@ -21,6 +21,50 @@ import util/[logging, constants, misc]
|
||||||
import core/[mainloop, fs, shutdown, services]
|
import core/[mainloop, fs, shutdown, services]
|
||||||
|
|
||||||
|
|
||||||
|
proc addStuff =
|
||||||
|
## Adds stuff to test NimD. This is
|
||||||
|
## a temporary procedure
|
||||||
|
|
||||||
|
# Adds symlinks
|
||||||
|
addSymlink(newSymlink(dest="/dev/fd", source="/proc/self/fd"))
|
||||||
|
addSymlink(newSymlink(dest="/dev/fd/0", source="/proc/self/fd/0"))
|
||||||
|
addSymlink(newSymlink(dest="/dev/fd/1", source="/proc/self/fd/1"))
|
||||||
|
addSymlink(newSymlink(dest="/dev/fd/2", source="/proc/self/fd/2"))
|
||||||
|
addSymlink(newSymlink(dest="/dev/std/in", source="/proc/self/fd/0"))
|
||||||
|
addSymlink(newSymlink(dest="/dev/std/out", source="/proc/self/fd/1"))
|
||||||
|
addSymlink(newSymlink(dest="/dev/std/err", source="/proc/self/fd/2"))
|
||||||
|
# Tests here. Check logging output (debug) to see if
|
||||||
|
# they work as intended
|
||||||
|
addSymlink(newSymlink(dest="/dev/std/err", source="/")) # Should say link already exists and points to /proc/self/fd/2
|
||||||
|
addSymlink(newSymlink(dest="/dev/std/in", source="/does/not/exist")) # Shuld say destination does not exist
|
||||||
|
addSymlink(newSymlink(dest="/dev/std/in", source="/proc/self/fd/0")) # Should say link already exists
|
||||||
|
# Adds virtual filesystems
|
||||||
|
addVFS(newFilesystem(source="proc", target="/proc", fstype="proc", mountflags=0u64, data="nosuid,noexec,nodev", dump=0u8, pass=0u8))
|
||||||
|
addVFS(newFilesystem(source="sys", target="/sys", fstype="sysfs", mountflags=0u64, data="nosuid,noexec,nodev", dump=0u8, pass=0u8))
|
||||||
|
addVFS(newFilesystem(source="run", target="/run", fstype="tmpfs", mountflags=0u64, data="mode=0755,nosuid,nodev", dump=0u8, pass=0u8))
|
||||||
|
addVFS(newFilesystem(source="dev", target="/dev", fstype="devtmpfs", mountflags=0u64, data="mode=0755,nosuid", dump=0u8, pass=0u8))
|
||||||
|
addVFS(newFilesystem(source="devpts", target="/dev/pts", fstype="devpts", mountflags=0u64, data="mode=0620,gid=5,nosuid,noexec", dump=0u8, pass=0u8))
|
||||||
|
addVFS(newFilesystem(source="shm", target="/dev/shm", fstype="tmpfs", mountflags=0u64, data="mode=1777,nosuid,nodev", dump=0u8, pass=0u8))
|
||||||
|
addDirectory(newDirectory("test", 777)) # Should create a directory
|
||||||
|
addDirectory(newDirectory("/dev/disk", 123)) # Should say directory already exists
|
||||||
|
addDirectory(newDirectory("/dev/test/owo", 000)) # Should say path does not exist
|
||||||
|
# Shutdown handler to unmount disks
|
||||||
|
addShutdownHandler(newShutdownHandler(unmountAllDisks))
|
||||||
|
# Adds test services
|
||||||
|
addService(newService(name="echoer", description="prints owo", exec="/bin/echo owo",
|
||||||
|
runlevel=Boot, kind=Oneshot, workDir=getCurrentDir(),
|
||||||
|
supervised=false, restart=Never, restartDelay=0))
|
||||||
|
addService(newService(name="errorer", description="la mamma di gavd",
|
||||||
|
exec="/bin/false", supervised=true, restart=OnFailure,
|
||||||
|
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple))
|
||||||
|
addService(newService(name="exiter", description="la mamma di licenziat",
|
||||||
|
exec="/bin/true", supervised=true, restart=Always,
|
||||||
|
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple))
|
||||||
|
addService(newService(name="sleeper", description="la mamma di danieloz",
|
||||||
|
exec="/usr/bin/sleep", supervised=true, restart=Always,
|
||||||
|
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple))
|
||||||
|
|
||||||
|
|
||||||
proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab") =
|
proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab") =
|
||||||
## NimD's entry point and setup
|
## NimD's entry point and setup
|
||||||
## function
|
## function
|
||||||
|
@ -53,26 +97,7 @@ proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab")
|
||||||
onSignal(SIGINT):
|
onSignal(SIGINT):
|
||||||
# Temporary
|
# Temporary
|
||||||
nimDExit(getDefaultLogger(), 131, emerg=true)
|
nimDExit(getDefaultLogger(), 131, emerg=true)
|
||||||
addSymlink(newSymlink(dest="/dev/fd", source="/proc/self/fd"))
|
addStuff()
|
||||||
addSymlink(newSymlink(dest="/dev/fd/0", source="/proc/self/fd/0"))
|
|
||||||
addSymlink(newSymlink(dest="/dev/fd/1", source="/proc/self/fd/1"))
|
|
||||||
addSymlink(newSymlink(dest="/dev/fd/2", source="/proc/self/fd/2"))
|
|
||||||
addSymlink(newSymlink(dest="/dev/std/in", source="/proc/self/fd/0"))
|
|
||||||
addSymlink(newSymlink(dest="/dev/std/out", source="/proc/self/fd/1"))
|
|
||||||
addSymlink(newSymlink(dest="/dev/std/err", source="/proc/self/fd/2"))
|
|
||||||
# Tests here. Check logging output (debug) to see if
|
|
||||||
# they work as intended
|
|
||||||
addSymlink(newSymlink(dest="/dev/std/err", source="/")) # Should say link already exists and points to /proc/self/fd/2
|
|
||||||
addSymlink(newSymlink(dest="/dev/std/in", source="/does/not/exist")) # Shuld say destination does not exist
|
|
||||||
addSymlink(newSymlink(dest="/dev/std/in", source="/proc/self/fd/0")) # Should say link already exists
|
|
||||||
# Adds virtual filesystems
|
|
||||||
addVFS(newFilesystem(source="proc", target="/proc", fstype="proc", mountflags=0u64, data="nosuid,noexec,nodev", dump=0u8, pass=0u8))
|
|
||||||
addVFS(newFilesystem(source="sys", target="/sys", fstype="sysfs", mountflags=0u64, data="nosuid,noexec,nodev", dump=0u8, pass=0u8))
|
|
||||||
addVFS(newFilesystem(source="run", target="/run", fstype="tmpfs", mountflags=0u64, data="mode=0755,nosuid,nodev", dump=0u8, pass=0u8))
|
|
||||||
addVFS(newFilesystem(source="dev", target="/dev", fstype="devtmpfs", mountflags=0u64, data="mode=0755,nosuid", dump=0u8, pass=0u8))
|
|
||||||
addVFS(newFilesystem(source="devpts", target="/dev/pts", fstype="devpts", mountflags=0u64, data="mode=0620,gid=5,nosuid,noexec", dump=0u8, pass=0u8))
|
|
||||||
addVFS(newFilesystem(source="shm", target="/dev/shm", fstype="tmpfs", mountflags=0u64, data="mode=1777,nosuid,nodev", dump=0u8, pass=0u8))
|
|
||||||
addShutdownHandler(newShutdownHandler(unmountAllDisks))
|
|
||||||
try:
|
try:
|
||||||
if mountDisks:
|
if mountDisks:
|
||||||
logger.info("Mounting filesystem")
|
logger.info("Mounting filesystem")
|
||||||
|
@ -82,31 +107,22 @@ proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab")
|
||||||
mountRealDisks(logger, fstab)
|
mountRealDisks(logger, fstab)
|
||||||
else:
|
else:
|
||||||
logger.info("Skipping disk mounting, assuming this has already been done")
|
logger.info("Skipping disk mounting, assuming this has already been done")
|
||||||
|
logger.info("Creating symlinks")
|
||||||
|
createSymlinks(logger)
|
||||||
|
logger.info("Creating directories")
|
||||||
|
createDirectories(logger)
|
||||||
|
logger.info("Filesystem preparation complete")
|
||||||
|
logger.debug("Calling sync() just in case")
|
||||||
|
doSync(logger)
|
||||||
except:
|
except:
|
||||||
logger.fatal(&"A fatal error has occurred while preparing filesystem, booting cannot continue. Error -> {getCurrentExceptionMsg()}")
|
logger.fatal(&"A fatal error has occurred while preparing filesystem, booting cannot continue. Error -> {getCurrentExceptionMsg()}")
|
||||||
nimDExit(logger, 131, emerg=false)
|
nimDExit(logger, 131, emerg=false)
|
||||||
logger.info("Disks mounted")
|
|
||||||
logger.debug("Calling sync() just in case")
|
|
||||||
doSync(logger)
|
|
||||||
logger.info("Setting hostname")
|
logger.info("Setting hostname")
|
||||||
logger.debug(&"Hostname was set to '{setHostname(logger)}'")
|
logger.debug(&"Hostname was set to '{setHostname(logger)}'")
|
||||||
logger.info("Creating symlinks")
|
|
||||||
createSymlinks(logger)
|
|
||||||
logger.info("Creating directories")
|
|
||||||
createDirectories(logger)
|
|
||||||
logger.debug("Entering critical fork() section: blocking signals")
|
logger.debug("Entering critical fork() section: blocking signals")
|
||||||
blockSignals(logger)
|
blockSignals(logger) # They are later unblocked in mainLoop
|
||||||
logger.info("Processing boot runlevel")
|
logger.info("Processing boot runlevel")
|
||||||
addService(newService(name="echoer", description="prints owo", exec="/bin/echo owo",
|
startServices(logger, workers=1, level=Boot)
|
||||||
runlevel=Boot, kind=Oneshot, workDir=getCurrentDir(),
|
|
||||||
supervised=false, restartOnFailure=false, restartDelay=0))
|
|
||||||
addService(newService(name="sleeper", description="la mamma di licenziato",
|
|
||||||
exec="/usr/bin/sleep 10", supervised=true, restartOnFailure=true,
|
|
||||||
restartDelay=5, runlevel=Boot, workDir="/home", kind=Simple))
|
|
||||||
addService(newService(name="errorer", description="la mamma di gavd",
|
|
||||||
exec="/bin/false", supervised=true, restartOnFailure=true,
|
|
||||||
restartDelay=5, runlevel=Boot, workDir="/", kind=Simple))
|
|
||||||
startServices(logger, workers=2, level=Boot)
|
|
||||||
logger.debug("Starting main loop")
|
logger.debug("Starting main loop")
|
||||||
mainLoop(logger)
|
mainLoop(logger)
|
||||||
|
|
||||||
|
@ -117,7 +133,8 @@ when isMainModule:
|
||||||
for kind, key, value in optParser.getopt():
|
for kind, key, value in optParser.getopt():
|
||||||
case kind:
|
case kind:
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
discard
|
echo "Error: unexpected argument"
|
||||||
|
quit(EINVAL)
|
||||||
of cmdLongOption:
|
of cmdLongOption:
|
||||||
case key:
|
case key:
|
||||||
of "help":
|
of "help":
|
||||||
|
@ -131,7 +148,7 @@ when isMainModule:
|
||||||
of "extra":
|
of "extra":
|
||||||
logger.setLevel(LogLevel.Trace)
|
logger.setLevel(LogLevel.Trace)
|
||||||
else:
|
else:
|
||||||
logger.error(&"Unkown command-line long option '{key}'")
|
echo &"Unkown command-line long option '{key}'"
|
||||||
quit(EINVAL) # EINVAL - Invalid argument
|
quit(EINVAL) # EINVAL - Invalid argument
|
||||||
of cmdShortOption:
|
of cmdShortOption:
|
||||||
case key:
|
case key:
|
||||||
|
@ -146,7 +163,9 @@ when isMainModule:
|
||||||
of "X":
|
of "X":
|
||||||
logger.setLevel(LogLevel.Trace)
|
logger.setLevel(LogLevel.Trace)
|
||||||
else:
|
else:
|
||||||
logger.error(&"Unkown command-line short option '{key}'")
|
echo &"Unkown command-line short option '{key}'"
|
||||||
|
echo "Usage: nimd [options]"
|
||||||
|
echo "Try nimd --help for more info"
|
||||||
quit(EINVAL) # EINVAL - Invalid argument
|
quit(EINVAL) # EINVAL - Invalid argument
|
||||||
else:
|
else:
|
||||||
echo "Usage: nimd [options]"
|
echo "Usage: nimd [options]"
|
||||||
|
@ -158,4 +177,4 @@ when isMainModule:
|
||||||
logger.fatal(&"A fatal unrecoverable error has occurred during startup and NimD cannot continue: {getCurrentExceptionMsg()}")
|
logger.fatal(&"A fatal unrecoverable error has occurred during startup and NimD cannot continue: {getCurrentExceptionMsg()}")
|
||||||
nimDExit(logger, 131) # ENOTRECOVERABLE - State not recoverable
|
nimDExit(logger, 131) # ENOTRECOVERABLE - State not recoverable
|
||||||
# This will almost certainly cause the kernel to crash with an error the likes of "Kernel not syncing, attempted to kill init!",
|
# This will almost certainly cause the kernel to crash with an error the likes of "Kernel not syncing, attempted to kill init!",
|
||||||
# but, after all, there isn't much we can do if we can't even initialize *ourselves* is there?
|
# but, after all, there isn't much we can do if we can't even initialize *ourselves* is there?
|
||||||
|
|
|
@ -75,7 +75,7 @@ proc getDefaultLogger*(): Logger =
|
||||||
## standard error with some basic info like the
|
## standard error with some basic info like the
|
||||||
## current date and time and the log level
|
## current date and time and the log level
|
||||||
|
|
||||||
setStdIoUnbuffered() # Just in case
|
setStdIoUnbuffered() # Doesn't work otherwise!
|
||||||
|
|
||||||
proc logTrace(self: LogHandler, logger: Logger, message: string) =
|
proc logTrace(self: LogHandler, logger: Logger, message: string) =
|
||||||
setForegroundColor(fgMagenta)
|
setForegroundColor(fgMagenta)
|
||||||
|
|
Loading…
Reference in New Issue