【问题标题】:How to print the timestamp on the terminal when user press Enter用户按 Enter 时如何在终端上打印时间戳
【发布时间】:2021-04-04 17:31:12
【问题描述】:

首先我是 Linux 和 Rust 的新手。

我想要实现的是每当用户在终端中执行命令时将时间戳打印到终端。

我编写了一个 Rust 程序,它将在终端的右端打印当前时间戳。我计划使用 bash 脚本在后台将这个程序作为systemd 服务执行。这个 bash 脚本所做的是在一个无限循环中,检查按键,如果是 Enter,然后执行 rust 程序。在我执行真正的 Rust 程序之前,我只是尝试echo 一个字符串。当我运行该服务时,我注意到当我按下 Enter 时,echo 在停止之前运行了很多次。我还尝试执行 Rust 程序而不是 echo,但它并没有像我想象的那样工作。所以我的解决方案是错误的。

我的问题是,我的方法正确吗?我不知道用无限循环运行后台进程是否好。这个想法是我从下面的视频中得到的。

Creating systemd Service Files

此项目用于教育目的。我受到Powerline 项目的启发,想了解它是如何工作的,并想用 Rust 小规模做一些类似的事情。

你们能否让我知道这种方法是否正确或指出我正确的方向。谢谢

ma​​in.rs

extern crate termion;
extern crate chrono;


use std::time::SystemTime;
use std::io::stdout;
use chrono::{DateTime, Utc};
use termion::{color, terminal_size, cursor, raw::IntoRawMode, cursor::DetectCursorPos};

fn main() {
    let mut stdout = stdout().into_raw_mode().unwrap();
    let cursor_pos = stdout.cursor_pos().expect("Could not get the cursor position");
    let time_now = SystemTime::now();
    let datetime = DateTime::<Utc>::from(time_now);
    let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S").to_string();
    let size = terminal_size().expect("Could not get the terminal size");
    let x = size.0 - (timestamp_str.len() - 1) as u16;
    let y = cursor_pos.1;
    print!("{}{red}{}{reset}",
        cursor::Goto(x, y),
        timestamp_str,
        red = color::Fg(color::Red),
        reset = color::Fg(color::Reset));
}

bash 脚本

#!/bin/bash

IFS=

while true
do
    read -n 1 key
    if [ "$key" = "" ]; then
        echo "This was really Enter, not space, tab or something else"
    fi
done

来自服务的日志

Apr 04 20:49:42 archlinux systemd[1]: Started cmd-timestamp.service.
Apr 04 20:49:42 archlinux cmd-timestamp.sh[410670]: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code:>
Apr 04 20:49:42 archlinux cmd-timestamp.sh[410670]: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Apr 04 20:49:42 archlinux systemd[1]: cmd-timestamp.service: Main process exited, code=exited, status=101/n/a
Apr 04 20:49:42 archlinux systemd[1]: cmd-timestamp.service: Failed with result 'exit-code'.

【问题讨论】:

  • 我认为 Powerline 根本不使用 systemd 功能。
  • 我来自网络开发背景。因此我没有任何与这种系统编程相关的经验。我试图找到任何指向正确方向的指南,但我找不到。这就是为什么在这里发布。所以你知道我可以通过其他方式实现这一目标吗?
  • 我不确定我是否完全理解您想要实现的目标。如果您正在谈论每次使用交互使用 bash 时打印时间戳,例如执行ls 或其他非交互运行的程序/脚本,最简单的方法是将您的程序用作bash 的PROMPT_COMMAND。通过将 ENTER 作为一项深深地连接到系统的服务来响应每一次按下 ENTER 似乎是一种彻底搞砸终端的方法......
  • @tink 这太好了。谢谢。我想我可以用它来执行我的 rust 应用程序 :)

标签: linux bash rust terminal systemd


【解决方案1】:

将评论带到答案部分:

完成我认为您想要的最简单的方法是通过PROMPT_COMMAND 将您的程序挂接到 bash。

在您的~/.bashrc(或~/.bash_login)集合中:

export PROMPT_COMMAND=/path/to/rust/executable

【讨论】:

  • export 有必要吗?
  • @Philippe - 随意尝试并返回您的发现。我的理解是exporting 使任何生成的子shell 都可以访问该变量...
  • 我在~/.bashrc 中实际使用的是CMD_TIMESTAMP=/path/to/rust/executable PROMPT_COMMAND=$PROMPT_COMMAND"; "$CMD_TIMESTAMP 这对我有用
  • @tink,当我们在~/.bashrc 中有PROMPT_COMMAND=/path/to/rust/executable 时,无论如何我们都有效果(在子shell 中也是如此),没有export。我看不到 OP 需要我们将变量传递给生成的子 shell。
猜你喜欢
  • 1970-01-01
  • 2016-07-12
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-19
相关资源
最近更新 更多