Stop command execution and exit process in raw mode.

huangapple go评论59阅读模式
英文:

Stop command execution and exit process in raw mode

问题

以下是翻译好的部分:

以下代码执行一个命令,然后允许您使用Ctrl + C退出进程:

use std::process::Command;
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::{stdin, stdout, Write};

fn main() {
    let stdin = stdin();
    let mut stdout = stdout().into_raw_mode().unwrap();
    let mut command = Command::new("script");

    command
        .arg("-qec")
        .arg("sleep 5 && echo test")
        .arg("/dev/null");

    let output = command.output();

    println!("output: {:?}", output);

    for c in stdin.keys() {
        match c.unwrap() {
            Key::Char(c) => println!("{}\r\n", c),
            Key::Ctrl('c') => {
                println!("Ctrl + C\r\n");
                write!(stdout, "{}", termion::cursor::Show).unwrap();
                std::process::exit(0);
            }
            _ => {}
        }
        stdout.flush().unwrap();
    }
}

您必须等待命令执行完成,然后才能按Ctrl + C退出程序。

如何在后台监听Ctrl + C,以便即使在命令运行时也能退出进程(类似于非原始模式中的中断命令)?

英文:

The following code executes a command, then enables you to exit the process with Ctrl + C:

use std::process::Command;

use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;

use std::io::{stdin, stdout, Write};

fn main() {
    let stdin = stdin();
    let mut stdout = stdout().into_raw_mode().unwrap();
    let mut command = Command::new("script");

    command
        .arg("-qec")
        .arg("sleep 5 && echo test")
        .arg("/dev/null");

    let output = command.output();

    println!("output: {:?}", output);

    for c in stdin.keys() {
        match c.unwrap() {
            Key::Char(c) => println!("{}\r\n", c),
            Key::Ctrl('c') => {
                println!("Ctrl + C\r\n");
                write!(stdout, "{}", termion::cursor::Show).unwrap();
                std::process::exit(0);
            }
            _ => {}
        }
        stdout.flush().unwrap();
    }
}

Rust Playground

You have to wait for the command to be executed to be able to press Ctrl + C and exit the program.

How to listen to Ctrl + C in the background so that the process can exit even when the command is running (interrupting the command like in non-raw mode)?

答案1

得分: 0

以下是您提供的代码的翻译部分:

我不确定这是否是最佳方法,但它有效。我生成了三个并发线程:一个用于`stdout`,另一个用于`stderr`,第三个用于监听Ctrl + C

use std::{
    io::{BufRead, BufReader},
    process::{Command, Stdio},
};

use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;

use std::io::{stdin, stdout, Write};

fn main() {
    let stdin = stdin();

    std::thread::spawn(move || {
        for c in stdin().keys() {
            match c.unwrap() {
                Key::Ctrl('c') => {
                    println!("Ctrl + C\r\n");
                    std::process::exit(0);
                }
                _ => {}
            }
        }
    });

    let mut stdout = stdout().into_raw_mode().unwrap();

    stdout.flush().unwrap();

    let mut command = Command::new("script");

    command
        .arg("-qec")
        .arg("sleep 5 && echo test")
        .arg("/dev/null");

    command.stdout(Stdio::piped());
    command.stderr(Stdio::piped());

    let mut child = command.spawn().expect("failed to spawn command");
    let stdout_pipe = child.stdout.take().unwrap();
    let stdout_reader = BufReader::new(stdout_pipe);
    let stderr_pipe = child.stderr.take().unwrap();
    let stderr_reader = BufReader::new(stderr_pipe);

    let stdout_thread = std::thread::spawn(move || {
        for line in stdout_reader.lines() {
            if let Ok(line) = line {
                print!("{}\r\n", line);
            }
        }
    });

    let stderr_thread = std::thread::spawn(move || {
        for line in stderr_reader.lines() {
            if let Ok(line) = line {
                print!("{}\r\n", line);
            }
        }
    });

    let status = child.wait().expect("failed to wait for command");

    stdout_thread.join().expect("failed to join stdout thread");
    stderr_thread.join().expect("failed to join stderr thread");

    println!("status: {}", status);
}

请注意,我只提供了代码的翻译部分,没有包括问题或其他内容。如果您需要任何其他帮助,请随时告诉我。

英文:

I'm not sure if this is the best method, but it works. I spawned three concurrent threads: one for stdout, another for stderr, and a third one for listening to Ctrl + C.

use std::{
    io::{BufRead, BufReader},
    process::{Command, Stdio},
};

use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;

use std::io::{stdin, stdout, Write};

fn main() {
    let stdin = stdin();
    
    std::thread::spawn(move || {
        for c in stdin().keys() {
            match c.unwrap() {
                Key::Ctrl('c') => {
                    println!("Ctrl + C\r\n");
                    std::process::exit(0);
                }
                _ => {}
            }
        }
    });
    
    let mut stdout = stdout().into_raw_mode().unwrap();
    
    stdout.flush().unwrap();

    let mut command = Command::new("script");

    command
        .arg("-qec")
        .arg("sleep 5 && echo test")
        .arg("/dev/null");

    command.stdout(Stdio::piped());
    command.stderr(Stdio::piped());

    let mut child = command.spawn().expect("failed to spawn command");
    let stdout_pipe = child.stdout.take().unwrap();
    let stdout_reader = BufReader::new(stdout_pipe);
    let stderr_pipe = child.stderr.take().unwrap();
    let stderr_reader = BufReader::new(stderr_pipe);

    let stdout_thread = std::thread::spawn(move || {
        for line in stdout_reader.lines() {
            if let Ok(line) = line {
                print!("{}\r\n", line);
            }
        }
    });

    let stderr_thread = std::thread::spawn(move || {
        for line in stderr_reader.lines() {
            if let Ok(line) = line {
                print!("{}\r\n", line);
            }
        }
    });

    let status = child.wait().expect("failed to wait for command");

    stdout_thread.join().expect("failed to join stdout thread");
    stderr_thread.join().expect("failed to join stderr thread");

    println!("status: {}", status);
}

Note: ctrl doesn't seem to work with Termion's raw mode.

huangapple
  • 本文由 发表于 2023年5月14日 15:39:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76246357.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定