Skip to content

Command muxing #102

@blinsay

Description

@blinsay

I've been using xshell in all of my xtasks (thanks for both the library and the pattern! ) and I found myself reaching for a Procfile-type thing to manage a couple commands simultaneously. Instead, I wrote a little crate that does to do the same thing with xshell::Cmds. Would you be interested in having something like it as a part of xshell?

Here's the current API:

    let sh = Shell::new().unwrap();
    let mut mux = muxshell::MuxCmd::new();

    let cmds = [
        (
            "foo",
            xshell::cmd!(sh, "bash -c 'while true; do echo foo; sleep 1; done'"),
        ),
        (
            "bar",
            xshell::cmd!(sh, "bash -c 'while true; do echo bar; sleep 2; done'"),
        ),
    ];
    for (name, cmd) in cmds {
        eprintln!("{name}: {cmd}");
        mux.add(name, cmd);
    }

    let output = mux.output();
    std::thread::spawn(move || {
        for output in output.iter() {
            match output.event {
                muxshell::Event::Output { stream, line } => {
                    println!("[{proc:<10}][{stream}] {line}", proc = output.process)
                }
                muxshell::Event::Exited { status } => {
                    println!("[{proc:<10}][exit] {status}", proc = output.process)
                }
            }
        }
    });
    mux.run().unwrap();

The example makes output that looks like this, but the idea is to just pass lines back to the caller as data and let them print them however they want.

$ cargo run --example multi-sleep
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/examples/multi-sleep`
foo: bash -c "while true; do echo foo; sleep 1; done"
bar: bash -c "while true; do echo bar; sleep 2; done"
[bar       ][stdout] bar
[foo       ][stdout] foo
[foo       ][stdout] foo
[bar       ][stdout] bar
[foo       ][stdout] foo
[foo       ][stdout] foo
[bar       ][exit] signal: 1 (SIGHUP)
[foo       ][stdout] foo
[foo       ][stdout] foo
[foo       ][stdout] foo
[foo       ][stdout] foo
[foo       ][stdout] foo
[foo       ][exit] signal: 31 (SIGUSR2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions