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.
|
||||
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...
|
||||
|
|
26
src/main.rs
26
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");
|
||||
|
||||
#[allow(unused_must_use)] {
|
||||
reboot(RebootMode::RB_POWER_OFF);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
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();
|
||||
()
|
||||
}
|
||||
|
|
15
src/svc.rs
15
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,15 +25,21 @@ 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/");
|
||||
|
||||
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
|
||||
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();
|
||||
services.push(svc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
services
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue