【问题标题】:Send key code to command line program on OS X向 OS X 上的命令行程序发送密钥代码
【发布时间】:2011-02-06 15:28:04
【问题描述】:

我想制作一个脚本来启动一个程序,然后向它发送按键输入。在伪脚本中:

#!/bin/bash
./program << (PRESS CONTROL-Z)

程序正在运行,因此如果脚本中有其他命令,除非说 control-z 终止程序,否则将无法访问它们。

这可能吗?根据我的发现,我认为它可能需要密钥,但我可能错了。

【问题讨论】:

  • CTRL+Z 在您从终端输入程序时暂停程序。如果在命令行中添加一个 & 符号,程序将在后台启动,并且在该程序执行时,将调用脚本的下一行。请参阅下面的答案。
  • 除非您的意思是程序本身需要某些用户按 CTRL+Z(并且它正在从 shell 中屏蔽此控制命令)?
  • 哦,这也许是有道理的,抱歉,我没有意识到这些是系统范围的热键。我需要的 Control-D 也是类似的,所以这个问题很简单。

标签: bash macos scripting keypress keycode


【解决方案1】:

我认为这可能是比“期望”更好的解决方案,因为它可以在本机 bash 脚本中执行,我很想看看你的想法。

使用

`printf "character code here"` 

注意反引号

例如,我编写了一个控制远程 gnu 屏幕会话的脚本,以下行打开窗口 2 并发出 ctrl-c 组合键

ssh -t user@$host screen -p 2 -X stuff `printf "\003"`
  • -t 选项模拟远程机器上的终端输入
  • -p 允许我们指定我们在屏幕会话中连接的窗口的名称或编号。
  • \003是字符码0x03的bash格式

有关代码的完整参考,请参阅here

要查找某些键输入的代码,您可以使用

printf "%#x\n" "'X"
0x58
  • Ware X 是您要查找代码的关键
  • 要查找非文字代码,您可以使用 ctrl-v(让 bash 将下一个键附加到命令行而不是解释它)然后键入组合键,所以如果我想找到 ctrl- 的键代码c 我会删除 X 按 ctrl-v 然后按 ctrl-c。

最后一件事上面提到的ascii代码参考将0x13列为回车符,但在屏幕手册中他们将0x15列为输入键代码,有人知道为什么吗?我已经在本地屏幕上进行了测试,当我按下回车键时会生成 0x13,但是当通过 ssh 向远程屏幕发送命令时,0x13 不起作用,但 0x15 可以。

希望有帮助

码头

【讨论】:

    【解决方案2】:

    如果您的意图是使程序后台运行,请使用:

    ./program &    # The & sends the command to the background
    echo commands here are executed while program is in the background
    …
    wait           # Wait for the completion of background commands
    echo commands here are executed after background program has completed
    

    编辑:如果您的意图是停止程序(就像 ctrl-Z 在 *nix shell 中经常做的那样),您可以向它发送 STOP 信号:

    kill -STOP pid
    

    要恢复执行,向它发送 CONT 信号:

    kill -CONT pid
    

    在每个示例中,pid 是程序的进程 ID。如果在脚本中启动它,很容易使用变量$!,例如

    ./prog &
    echo prog started in the background
    pid_of_prog=$!
    kill -STOP $pid_of_prog
    echo prog stopped
    kill -CONT $pid_of_prog
    echo prog continues
    wait
    echo prog finished
    

    编辑 2: 如果您的程序是在收到 ctrl-Z 字符时退出的程序,请记住控制字符具有字母表中位置字母的数值(即 Ctrl- A 是 1,Ctrl-B 是 2,等等)。要将此字符发送到程序,您可以:

    echo -e "\032" | ./prog
    

    (032 是 26,即 ^Z,以八进制表示。当然,您可以通过任何方式生成相同的字符,也许将其添加到其他输入的末尾,例如 ( cat inputfile ; echo -e "\032" ) | ./prog

    但这不一定有效;程序必须设计为从输入中识别这个字符(它可能不会);通常外壳会捕获它。再说一次,大多数从stdin 读取输入的程序都会在输入结束时退出,因此重定向任何有限输入(甚至是&lt;/dev/null)都会导致它终止。

    最后,如果目的是在发生其他事件(在脚本的其他地方检测到)时停止程序的执行,您可以kill它...

    【讨论】:

    • 这听起来不错,但我不确定在后台进程中按下 control-z 的效果如何。
    • @Sandy Vanderbleek:我仍然不太确定你所追求的 ctrl-z 应该做什么,但我用一些替代方案编辑了答案。
    【解决方案3】:

    如果你只是想让程序在后台启动,就这样做

    #!/bin/bash
    ./program&
    

    【讨论】:

      【解决方案4】:

      您可能正在寻找expect(来自http://expect.nist.gov/)。这处理了伪 tty 的复杂性,使程序看起来脚本的输入(在本场景中为 expect 程序)来自终端。

      或者,您也可以使用 echocat 并将其输出通过管道传输到程序中 - 这取决于程序。

      【讨论】:

      • 通过管道进入程序的事情是我需要某种方式来模拟控制键,这不仅仅是文本命令。
      • @Sandy Vanderbleek:一般不会,不。您可以将控制字符回显到命令中,但通常这些字符的处理方式与按下例如在 shell 中按 Ctrl-Z(在这种情况下,它是 shell,而不是命令,它获取输入)。
      • @Sandy:如果程序处理字符,则控制字符不会出现特别问题。如果您的程序正在检测按键的按下和释放,那么您将遇到更大的问题。当然,echo 和 cat 都不会处理按键。我怀疑 expect 也不会 - 但这需要一些检查。
      • 我认为 expect 会起作用,因为我研究了它,谢谢。我仍然需要弄清楚如何使用expect。
      • @Arkku:请注意,使用伪 tty 和 expect 的原因之一是让您确实在键入 control-Z 时获得 ^Z 的效果。
      猜你喜欢
      • 2011-05-23
      • 2023-03-23
      • 2010-11-07
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2011-12-11
      • 1970-01-01
      相关资源
      最近更新 更多