6

我正在编写一个 bash 包装器来学习一些脚本概念。这个想法是在 bash 中编写一个脚本,并在登录时将其设置为用户的 shell。

我做了一个 while 循环reads 和evals 用户的输入,然后注意到,每当用户键入CTRL + C时,脚本都会中止,因此用户会话结束。

为了避免这种情况,我陷入SIGINT了陷阱,在陷阱中什么也不做。

现在,问题是当您键入CTRL + C命令的一半时,它不会像在 bash 上那样被取消 - 它只是忽略CTRL + C.

所以,如果我输入ping stockoverf^Cping stackoverflow.com,我得到ping stockoverfping stackoverflow.com的不是ping stackoverflow.com我想要的。

有没有办法做到这一点?

#!/bin/bash

# let's trap SIGINT (CTRL + C)
trap "" SIGINT

while true
do
    read -e -p "$USER - SHIELD: `pwd`> " command
    history -s $command
    eval $command
done
4

2 回答 2

3

您可以使用 xdotool 之类的工具发送 Ctrl-A(行首) Ctrl-K(删除到行尾) Return(清理行)

#!/bin/bash
trap "xdotool key Ctrl+A Ctrl+k Return" SIGINT;
unset command
while [ "$command" != "quit" ] ;do
    eval $command
    read -e -p "$USER - SHIELD: `pwd`> " command
  done
trap SIGINT

但我强烈邀请你到 rtfm... 在搜索 ``debug'' 关键字...

man -Pless\ +/debug bash
于 2012-10-24T22:34:37.097 回答
3

我知道这已经很老了,但我一直在努力做这样的事情并想出了这个解决方案。希望它可以帮助别人!

#/usr/bin/env bash
# Works ok when it is invoked as a bash script, but not when sourced!
function reset_cursor(){
    echo
}
trap reset_cursor INT
while true; do
    command=$( if read -e -p "> " line ; then echo "$line"; else echo "quit"; fi )
    if [[ "$command" == "quit" ]] ; then
        exit
    else
        history -s $command
        eval "$command"
    fi
done
trap SIGINT

通过将读取放入子shell,您可以确保它会被 sigint 信号杀死。如果您在该信号渗透到父级时捕获该信号,则可以在那里忽略它并移至下一个 while 循环。您不必将 reset_cursor 作为其自己的功能,但如果您想做更复杂的事情,我觉得它很好。

我必须在子 shell 中添加 if 语句,否则它会忽略 ctrl+d - 但我们希望它能够“注销我们”而不强制用户键入 exit 或手动退出。

于 2020-09-02T21:28:14.477 回答