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 / 问题 / 436959
Accepted
Taapo
Taapo
Asked: 2018-04-12 01:11:20 +0800 CST2018-04-12 01:11:20 +0800 CST 2018-04-12 01:11:20 +0800 CST

如何在退出屏幕之前获得确认?

  • 772

如何在退出屏幕之前获得确认(在命令行上键入 exit 时)。这可能吗?

gnu-screen exit
  • 3 3 个回答
  • 1013 Views

3 个回答

  • Voted
  1. Best Answer
    Jeff Schaller
    2018-04-14T17:47:51+08:002018-04-14T17:47:51+08:00

    我通过exit用函数屏蔽命令来解决这个问题;该函数检查您是否在屏幕内,以及您是否是该屏幕进程剩下的唯一子进程。

    exit() {
      if  [[ "$(ps -o pid= --ppid "$(ps -o ppid= -p "$$")" | wc -l)" -eq 1 ]]
      then
        read -p "Warning: you are in the last screen window; do you really want to exit? (y/n) "
        case $REPLY in
            (y*) command exit "$@" ;;
        esac
      else
        # not within screen at all, or not within the last screen window
        command exit "$@"
      fi
    }
    

    您必须将该功能包含在您的(bash)配置文件中,例如~/.bash_profile. 启动屏幕时,它将(除非另有说明)启动您的 $SHELL 实例。该外壳将是屏幕进程的子进程。当从子 shell 退出时,上面的代码检查有多少进程是当前 shell 的父进程的子进程。从里到外:

    • $(ps -o ppid= -p "$$")-- 询问=当前进程的父 PID(添加抑制标题行)($$)
    • $(ps -o pid= --ppid ... | wc -l)-- 询问其父 PID 是我们父级的 PID 列表(同样没有标题),然后计算输出的行数

    如果看起来我们是屏幕会话的最后一个子进程,它会提示确认;如果响应以字母开头y,函数调用“real”exit命令退出shell;否则,函数在不退出 shell 的情况下结束。

    如果我们不是最后一个子进程,则函数继续执行并正常退出。

    我开发这个时有几点注意事项:

    • 我最初在该if行中进行了更多测试,以查看我们是否在屏幕会话中,包括查看是否STY已填充以及SHLVL是否大于 1。屏幕设置 STY,而 bash 将增加 SHLVL,但这些变量都不是只读的,所以测试不够强大,没有用。

    • screen 也设置了一个WINDOW变量,但检查它0是不可靠的;您可以打开两个窗口,然后关闭 window 0,将 window1作为最后一个窗口。

    • 默认情况下,输入 EOF(通常是Control+ D)会导致 shell 立即退出,绕过这个包装函数。我知道的最好的解决方法是将变量设置IGNOREEOF为某个非零值;不过,这只会延迟 shell 不可避免的退出。

    因为我在上面使用了很多 bash-(和 GNU procutils-)特定功能,所以我还想提供一个符合 POSIX 的解决方案。该ps行更改为一个ps ... | grep -c方案,以捕获具有特定父 PID 的进程数。另一个更改是将 重新工作read -p为单独的提示和read.

    exit() {
      parent="$(ps -o ppid= -p $$)"
      if [ "$( ps -eo ppid= | grep -c "^ *${parent}\$" )" -eq 1 ]
      then
        printf "Warning: you are in the last screen window; do you really want to exit? (y/n) "
        read REPLY
        case $REPLY in
            (y*) command exit "$@" ;;
        esac
      else
        # not within screen at all, or not within the last screen window
        command exit "$@"
      fi
    }
    
    • 3
  2. alzee
    2018-04-15T00:18:08+08:002018-04-15T00:18:08+08:00

    我假设您正在使用 bash。

    are_u_sure(){
            read -n1 -p "Are you sure to exit? [y/N] "
            [ "$REPLY" != y ] && { echo; history -a; bash; }
    }
    
    trap are_u_sure EXIT
    

    将此添加到您的 ~/.bashrc 中,然后每当您尝试退出 bash(键入 exit 或 ^D)时,系统都会提示您。除非你按'y',否则你永远不会退出。

    这样,我们就不必拘泥于屏幕魔法,因为我们可以在 bash 范围内进行。

    由于这种方法非常简单,它确实有一个缺陷,你会丢失你之前输入的变量赋值。但也许我们可以解决这个问题。无论如何,您都可以修改此代码以满足您的需要。

    • 0
  3. Wedge
    2020-04-15T15:01:17+08:002020-04-15T15:01:17+08:00

    我对我在那里看到的任何其他解决方案都不满意,所以我最终解决了这个问题(添加到 .bashrc):

    exit_with_prompt() {
        printf "Do you really want to exit screen? (y/n) "
        read REPLY
        case $REPLY in
            (y*) command exit "$@" ;;
        esac
    }
    
    export IGNOREEOF=0
    [[ $(type -t exit) == "alias" ]] && unalias exit
    [[ $(type -t logout) == "alias" ]] && unalias logout
    
    if grep -q "^screen\b" /proc/$PPID/comm; then
        export IGNOREEOF=2
        alias exit=exit_with_prompt
        alias logout=exit_with_prompt
    fi
    

    然后这个到.screenrc:

    shell -$SHELL
    

    这与我通常做事的方式有点倒退。它取消设置别名并重新启用 ctrl-d -> 正常退出,但它检查 bash 是否立即在屏幕实例内运行(特别是它检查父进程的命令的开始是否是“屏幕”,然后是单词边界),然后它会禁用 ctrl-d/EOF 退出并使用退出和注销的提示别名设置退出。

    我已经很久没有使用它了,但到目前为止我对它的工作方式非常满意。

    • 0

相关问题

  • 如何在屏幕下取消冻结我的 vim 会话

  • 如何通过串行控制台以分离模式运行 GNU 屏幕并保存输出?

  • eval 的返回值

  • 串行设备输出在 gnu 屏幕中看起来不错,但使用 cat 时出现乱码

  • 为什么 macOS 上的 screen 不接收我的 ~/.terminfo?

Sidebar

Stats

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

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +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