Browse Source

add deploy script & some minor cleanup

master
darkgallium 1 year ago
parent
commit
15495a2eb9
  1. 31
      Makefile
  2. 6
      README.md
  3. 28
      src/main.rs
  4. 39
      src/processes.rs
  5. 21
      src/svc.rs

31
Makefile

@ -0,0 +1,31 @@
build:
su florian -c "cargo build"
setup-nbd:
modprobe nbd max_part=8
qemu-nbd --connect=/dev/nbd0 /home/florian/.vm/arch.qcow
mkdir -p /mnt/arch-mini
mkdir -p /mnt/arch-mini-boot
sleep 1
mount /dev/nbd0p1 /mnt/arch-mini-boot
mount /dev/nbd0p2 /mnt/arch-mini
sleep 1
change-boot-mini:
sed -i 's/quiet/init\=\/root\/mini/' /mnt/arch-mini-boot/grub/grub.cfg
change-boot-systemd:
sed -i 's/init\=\/root\/mini/quiet/' /mnt/arch-mini-boot/grub/grub.cfg
cleanup-nbd:
umount /mnt/arch-mini{,-boot}
qemu-nbd -d /dev/nbd0
vm:
su florian -c "bash -c 'cd /home/florian/.vm && ./arch-mini.sh'"
copy-mini:
cp target/debug/mini /mnt/arch-mini/root/
run: build setup-nbd copy-mini change-boot-mini cleanup-nbd vm
run-systemd: build setup-nbd change-boot-systemd copy-mini cleanup-nbd vm

6
README.md

@ -2,6 +2,7 @@
mini is a minimal init system.
It was created mainly for educational purposes as well as wanting to know if I were able to reduce my Arch boot time.
You may use it at your own risk, it is not ready for any serious use (and will probably never be :)).
## Install
@ -10,3 +11,8 @@ It was created mainly for educational purposes as well as wanting to know if I w
3. `cp target/debug/mini /sbin/`
4. Create your services files if needed
5. Edit the kernel command line and add `init=/sbin/mini`
## Developing
To ease development, I created a Makefile that will automatically compile and deploy latest version of mini on a QEMU VM.
More details to come...

28
src/main.rs

@ -1,13 +1,12 @@
mod processes;
mod svc;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::process;
use std::error::Error;
use signal_hook::{SIGINT, SIGCHLD, SIGALRM, SIGUSR1};
use signal_hook::{SIGINT, SIGCHLD, SIGUSR1};
use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
use nix::sys::reboot::{reboot, RebootMode};
use nix::sys::signal::Signal;
@ -56,17 +55,17 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!();
println!("remount /");
processes::run_wait("mount", ["-o", "remount", "/"].as_ref()).await;
processes::run("mount", ["-o", "remount", "/"].as_ref()).await;
println!("set hostname");
set_hostname();
println!("mount all partitions");
processes::run_wait("mount", ["-a"].as_ref()).await;
processes::run("mount", ["-a"].as_ref()).await;
processes::run("swapon", ["-a"].as_ref()).await;
println!("load udev");
processes::run_wait("/usr/lib/systemd/systemd-udevd", ["-d"].as_ref()).await;
processes::run("/usr/lib/systemd/systemd-udevd", ["-d"].as_ref()).await;
processes::run("udevadm", ["trigger", "--action=add", "--type=subsystems"].as_ref()).await;
processes::run("udevadm", ["trigger", "--action=add", "--type=devices"].as_ref()).await;
processes::run("udevadm", ["settle"].as_ref()).await;
@ -75,8 +74,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
processes::run("loadkeys", ["fr-latin9"].as_ref()).await;
println!("load dbus");
processes::run_wait("mkdir", ["/run/dbus"].as_ref()).await;
processes::run_wait("dbus-daemon", ["--system"].as_ref()).await; // a lot of services depend on dbus being on
processes::run("mkdir", ["/run/dbus"].as_ref()).await;
processes::run("dbus-daemon", ["--system"].as_ref()).await; // a lot of services depend on dbus being on
println!("now loading your services");
svc::launch_services().await;
@ -98,15 +97,22 @@ async fn main() -> Result<(), Box<dyn Error>> {
let pids = processes::get_all_pids();
for pid in pids {
kill(Pid::from_raw(pid), Signal::SIGKILL);
let res = kill(Pid::from_raw(pid), Signal::SIGKILL);
match res {
Ok(_) => {}
Err(err) => eprintln!("error killing process {}, error is {}", pid, err)
}
}
println!("unmounting all partitions");
processes::run_wait("swapoff", ["-a"].as_ref()).await;
processes::run_wait("umount", ["-a", "-f"].as_ref()).await;
processes::run("swapoff", ["-a"].as_ref()).await;
processes::run("umount", ["-a", "-f"].as_ref()).await;
println!("end pre-shutdown routines");
reboot(RebootMode::RB_POWER_OFF);
#[allow(unused_must_use)] {
reboot(RebootMode::RB_POWER_OFF);
}
Ok(())
}

39
src/processes.rs

@ -2,6 +2,8 @@ use std::fs;
use std::process::{Stdio, Command};
use tokio::process::Command as AsyncCommand;
use tokio::process::Child as AsyncChild;
use std::io::Error;
use tokio;
pub fn get_all_pids() -> Vec<i32> {
let mut pids = Vec::<i32>::new();
@ -17,7 +19,7 @@ pub fn get_all_pids() -> Vec<i32> {
if pid > 1 {
let content = fs::read_to_string(format!("/proc/{}/cmdline", pid));
match content {
Ok(cmdline) => {
Ok(_) => {
//if cmdline != "" {
pids.push(pid);
//}
@ -48,22 +50,29 @@ pub fn sync_run_wait(path: &str, args: &[&str]) {
}
pub async fn run(path: &str, args: &[&str]) -> AsyncChild {
async fn _run_cmd(path: &str, args: &[&str]) -> Result<AsyncChild, Error> {
AsyncCommand::new(path)
.env("PATH", "/sbin:/bin:/usr/bin")
.args(args)
.stdout(Stdio::null())
.spawn()
.unwrap()
.env("PATH", "/sbin:/bin:/usr/bin")
.args(args)
.stdout(Stdio::null())
.spawn()
}
pub async fn run_wait(path: &str, args: &[&str]) {
let child = AsyncCommand::new(path)
.env("PATH", "/sbin:/bin:/usr/bin")
.args(args)
.spawn()
.unwrap();
// async closures are not supported yet so here's some code duplication that I'll get rid of eventually
pub async fn run(path: &str, args: &[&str]) {
let res = _run_cmd(path, args).await;
match res {
Ok(child) => {
let pid = child.id();
match child.await {
Ok(_) => {},
Err(err) => eprintln!("failed to wait for process with pid {}, error is {}", pid, err)
}
},
Err(err) => eprintln!("could not spawn {}, error is {}", "", err)
}
child.await.unwrap();
()
}

21
src/svc.rs

@ -1,8 +1,7 @@
use std::fs;
use std::{fs, path::Path};
use serde::Deserialize;
use toml;
use tokio;
use crate::processes;
#[derive(Deserialize, Debug)]
@ -26,13 +25,19 @@ pub struct Stop {
pub fn get_services() -> Vec<Service> {
let mut services = Vec::new();
let paths = fs::read_dir("/etc/mini/").unwrap();
let mini_dir = Path::new("/etc/mini/");
if mini_dir.exists() && mini_dir.is_dir() {
let dir = fs::read_dir(mini_dir).unwrap();
for file in dir {
// TODO: check ext
let svc_file_contents = fs::read_to_string(file.unwrap().path()).unwrap();
let svc : Service = toml::from_str(&svc_file_contents).unwrap();
services.push(svc);
}
for path in paths {
// TODO: check ext
let svc_file_contents = fs::read_to_string(path.unwrap().path()).unwrap();
let svc : Service = toml::from_str(&svc_file_contents).unwrap();
services.push(svc);
}
services

Loading…
Cancel
Save