AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 408804
Accepted
Arcticooling
Arcticooling
Asked: 2017-12-05 12:00:38 +0800 CST2017-12-05 12:00:38 +0800 CST 2017-12-05 12:00:38 +0800 CST

从现在开始的某个时间做某事(也许还会在控制台中显示结果)

  • 772

我使用 Ubuntu 服务器 16.04,并且我希望at在当前会话中使用该实用程序在 1 分钟后执行某项操作(例如 an echo),但没有给出具体的日期和时间 - 仅比当前时间提前 1 分钟。

这失败了:

echo 'hi' | at 1m

我选择的原因at是sleep因为 sleep 会妨碍当前会话,因此更适合在另一个会话中延迟命令,而不是我们大部分时间使用的命令。AFAIR,at不这样做,不会妨碍我的会话。

更新_1

通过 Pied Piper 的回答,我尝试过:

(sleep 1m; echo 'hi')  &

我对这种方法有疑问:“hi”流打印在我的主提示符内,并且还在_包含它的主提示符下方添加了一个空的辅助提示符 ( ),请参阅:

USER@:~# (sleep 1m; echo 'hi')  &
[1] 22731
USER@:~# hi
^C
[1]+  Done

更新_2

根据彼得科德的回答,我试过:

(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)

这在 Bash 4.4 中可以正常工作,但在某些旧版本中似乎不行(请参阅答案中的评论)。我个人在自己的环境中使用 Bash 4.3。

console stdout
  • 6 6 个回答
  • 1753 Views

6 个回答

  • Voted
  1. Marcelo
    2017-12-05T12:40:04+08:002017-12-05T12:40:04+08:00

    正确的用法是,时间规范at <timespec>在哪里。<timespec>您还可以使用该-f选项来指定包含要执行的命令的文件。如果-f不使用重定向,则 at 将读取从标准输入(标准输入)执行的命令。

    在您的示例中,在您按下回车后一分钟(现在)执行“some command”(我在下面的示例中选择“some command”为“echo hi”),预期<timespec>使用的是now + 1 minute. 因此,为了通过单线解决方案获得您想要的结果,请使用以下命令:

    echo 'echo hi' | at now + 1 minute

    这应该(并且会)echo hi在一分钟后运行命令。这里的问题是该echo hi命令将由 at 命令在虚拟 tty 中执行,并且输出将被发送到用户的邮箱(如果配置正确 - 这需要更广泛地解释如何在一台unix机器,不属于这个问题的范围)。最重要的是,您将无法echo hi在发出命令的同一终端中直接看到结果。最简单的选择是将其重定向到“某个文件”,例如:

    echo 'echo hi > /tmp/at.out' | at now + 1 minute

    在上面的例子中,“some file”是/tmp/at.out,预期的结果是at.out/tmp 下的文件在一分钟后创建并包含文本“hi”。

    除了上面的now + 1 minute示例之外,还可以使用许多其他时间规范,甚至是一些复杂的时间规范。at 命令足够聪明,可以解释非常易读的命令,如下例所示:

    now + 1 day, 13:25, mid‐night, noon, ...

    有关可能的时间规范的更多信息,请参阅 at 的手册页,因为可能的变化非常广泛,可能包括日期、相对或绝对时间等。

    • 13
  2. PiedPiper
    2017-12-05T12:22:23+08:002017-12-05T12:22:23+08:00

    在子shell中运行sleep:

    (sleep 60; echo -e '\nhi')  &
    

    注意:在 Linux 上,您可以以秒或后缀 s/m/h/d(表示秒、分钟、小时、天)给出睡眠参数。在 BSD 上,参数必须以秒为单位

    • 7
  3. Best Answer
    Peter Cordes
    2017-12-05T17:04:23+08:002017-12-05T17:04:23+08:00

    “hi”流打印在我的提示符中(在 中stdin)而不是我的stdout

    不,它不是“印在你的stdin”上的。

    如果您按下回车键,它不会尝试hi作为命令运行。只是当光标在您的提示之后echo打印的背景。hi


    也许你想打印一个领先的换行符,比如(sleep 1m && echo -e '\nhi' &). (根据需要调整echoshell 中的。或printf用于可移植性。)

    我将&subshel​​l 放在里面来“拒绝”后台作业,这样你也可以避免[1]+ Done. 在&&命令之间,适用于整个复合命令链,因此它会立即返回到 shell 提示符,而不是像您使用&的那样等待退出sleep(sleep 1; echo ... &)

    这是发生的事情(延迟 1 秒):

    peter@volta:~$ (sleep 1 && echo -e '\nhi' &)
    peter@volta:~$ 
    hi
           # cursor is at the start of this empty line.
    

    Bash 不知道echo打印了什么,所以它不知道它需要重新打印它的提示或清理屏幕。您可以使用 手动执行此操作control-L。

    您可以编写一个 shell 函数,让 bash 在完成后重新打印其提示echo。只是这样做echo "$PS1"不会重现任何已经输入的字符。 kill -WINCH $$在我的系统上让 bash 在不清除屏幕的情况下重新打印其提示行,hi在提示之前单独保留一行。当 WINdow 大小发生变化时会自动发送 SIGWINCH,而 bash 对它的响应恰好符合我们的要求。

    它可能适用于其他 shell,但我并没有试图让这个 100% 可移植/POSIX。(不幸的是,这只适用于 bash4.4,不适用于 bash4.3,或者取决于我不知道的某些设置)

      # bash4.4
    peter@volta:~$ (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
    peter@volta:~$ ljlksjksajflasdf dfas      # typed in 2 seconds
    hi
    peter@volta:~$ ljlksjksajflasdf dfas      # reprinted by Bash because of `kill -WINCH`
    

    您可以轻松地将其包装在一个带有 sleep arg 和消息的 shell 函数中。

    bash 4.3 在 SIGWINCH 之后不会重新打印它的提示,所以这在那里不起作用。我shopt -s checkwinsize在两个系统上都启用了,但它只适用于 Bash 4.4 系统(Arch Linux)。

    如果它不起作用,您可以尝试(sleep 2 && echo -e '\nhi' && echo "$PS1" &),如果命令行为空,它会“起作用”。(它也忽略了设置的可能性PROMPT_COMMAND。)


    当计时器触发时,没有真正干净的方法可以让终端输出与您以后可能在终端上执行的任何操作混合。如果您正在滚动某些内容less,您很容易错过它。

    如果您正在寻找具有交互式结果的内容,我建议您播放音频文件。例如使用命令行播放器mpv(MPlayer2 的好分支)。或者选择一个视频文件,以便打开一个新窗口。

    (sleep 1 && mpv /f/share/music/.../foo.ogg </dev/null &>/dev/null &)
    

    您可能希望echo打开一个新的 xterm / konsole / gnome-terminal。使用在命令退出后保持终端打开的选项。

    • 6
  4. Austin Hemmelgarn
    2017-12-05T12:34:57+08:002017-12-05T12:34:57+08:00

    那失败了,因为您正在管道输出echo "hi",这只是hi到at,但at期望它的输入可以由默认系统 shell 执行(通常是 bash,但有时会因系统而异)。

    这个:

    at 1m << EOF
    echo "hi"
    EOF
    

    将实现您似乎正在尝试做的事情。它使用称为“here document”的 shell 构造,这通常是执行此类操作的公认方式(因为它比使用echo命令更好地处理多行,并且不需要像您需要的那样创建新文件)cat),并使用以下转换为更复杂的等价物echo:

    echo 'echo "hi"' | at 1m
    

    可能值得注意的是,at它将任何命令输出邮寄给调用该at命令的用户,而不是像在子shell 中延迟使用的命令那样将输出写入终端sleep。特别是,这意味着除非您对系统进行了一些自定义,或者打算读取本地邮件假脱机,否则您将无法获得通过at.

    • 3
  5. Bruce
    2017-12-09T01:22:39+08:002017-12-09T01:22:39+08:00

    结合@Peter Cordes的答案和这个答案 https://stackoverflow.com/questions/23125527/how-to-return-to-bash-prompt-after-printing-output-from-backgrounded-function/23125687#23125687

    下面的代码来自后一个答案,我做了一点改动。将其编译到文件 a.out(您喜欢的任何名称)

    #include <sys/ioctl.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
            char *tty = "/dev/tty";
            if (argc > 1)
                    tty = argv[1];
            int fd = open(tty, O_WRONLY);
    
            int i;
            char buf[] = "\n";
            for (i = 0; i < sizeof buf - 1; i++)
                    if (ioctl(fd, TIOCSTI, &buf[i]))
                            perror("ioctl");
            close(fd);
            return 0;
    }
    

    然后运行下面的命令。(我把 a.out 放在 /tmp/ 目录下,你可能需要换成你的)

    (sleep 2 && echo -e '\nhi' && /tmp/a.out &)
    

    或者

    (sleep 2 && echo -e '\nhi' && /tmp/a.out /proc/$$/fd/0 &)
    

    顺便说一句,kill -WINCH $$在 Gentoo 上使用 Bash 4.3 对我来说效果很好。

    • 2
  6. user1404316
    2017-12-08T20:17:57+08:002017-12-08T20:17:57+08:00

    基于上面的答案,您可以让嵌入式命令将其输出定向到您的终端,如下所示:

    echo "echo hi >$(tty); kill -WINCH $$" | at now + 1 minute

    该tty命令返回当前终端的设备路径,将其包含在$(...)bash 中,在子 shell 中执行它,并且 kill 命令向当前进程发送一个信号,让 bash 重新打印其 $PS1 提示符。

    • 1

相关问题

  • 在后台回显某些内容,但即使您重新启动或停电也能看到它?

  • 如何让我的帧缓冲控制台工作?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    JSON数组使用jq来bash变量

    • 4 个回答
  • Marko Smith

    日期可以为 GMT 时区格式化当前时间吗?[复制]

    • 2 个回答
  • Marko Smith

    bash + 通过 bash 脚本从文件中读取变量和值

    • 4 个回答
  • Marko Smith

    如何复制目录并在同一命令中重命名它?

    • 4 个回答
  • Marko Smith

    ssh 连接。X11 连接因身份验证错误而被拒绝

    • 3 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Marko Smith

    systemctl 命令在 RHEL 6 中不起作用

    • 3 个回答
  • Marko Smith

    rsync 端口 22 和 873 使用

    • 2 个回答
  • Marko Smith

    以 100% 的利用率捕捉 /dev/loop -- 没有可用空间

    • 1 个回答
  • Marko Smith

    jq 打印子对象中所有的键和值

    • 2 个回答
  • Martin Hope
    EHerman JSON数组使用jq来bash变量 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux 日期可以为 GMT 时区格式化当前时间吗?[复制] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC 如何复制目录并在同一命令中重命名它? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve “root”用户的文件权限如何工作? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe 将默认编辑器更改为 vim for _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey 如何下载软件包而不是使用 apt-get 命令安装它? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao 为什么目录 /home、/usr、/var 等都具有相同的 inode 编号 (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg —list-keys 命令在将私钥导入全新安装后输出 uid [未知] 2017-11-26 18:26:02 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve