add deploy script & some minor cleanup
This commit is contained in:
parent
637a3bc9b9
commit
15495a2eb9
5 changed files with 91 additions and 34 deletions
31
Makefile
Normal file
31
Makefile
Normal 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
|
|
@ -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...
|
||||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -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");
|
||||||
reboot(RebootMode::RB_POWER_OFF);
|
|
||||||
|
#[allow(unused_must_use)] {
|
||||||
|
reboot(RebootMode::RB_POWER_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
()
|
|
||||||
}
|
}
|
||||||
|
|
21
src/svc.rs
21
src/svc.rs
|
@ -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,13 +25,19 @@ 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/");
|
||||||
|
|
||||||
|
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
|
services
|
||||||
|
|
Loading…
Reference in a new issue