add deploy script & some minor cleanup

This commit is contained in:
darkgallium 2020-06-20 15:27:21 +02:00
parent 637a3bc9b9
commit 15495a2eb9
5 changed files with 91 additions and 34 deletions

31
Makefile Normal file
View file

@ -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

View file

@ -2,6 +2,7 @@
mini is a minimal init system. 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. 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 ## 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/` 3. `cp target/debug/mini /sbin/`
4. Create your services files if needed 4. Create your services files if needed
5. Edit the kernel command line and add `init=/sbin/mini` 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...

View file

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

View file

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

View file

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