【问题标题】:Checking if a Screen of the Specified Name Exists检查指定名称的画面是否存在
【发布时间】:2012-09-04 00:28:04
【问题描述】:

我制作了一个 bash 文件,它在分离的屏幕中启动另一个具有唯一名称的 bash 文件,我需要确保在任何一个时间点只有一个该内部 bash 文件的实例正在运行。为此,我想让父 bash 文件检查该名称的屏幕是否存在,然后再尝试创建它。有没有办法做到这一点?

【问题讨论】:

  • 如果您喜欢screen,请考虑尝试tmux。有很多不同,但值得转换。
  • 我主要使用 screen 来实现其类似守护进程的功能,因为没有更好的选择。如果 tmux 与 CLI 的协作与 screen 一样(例如,允许通过 bash 将命令注入正在运行的屏幕中),那么我确实可以切换。
  • 这个线程非常棒,非常适合我的用例......我一直在使用 pgrep 和 pkill,但是 -Q 和 -X 非常适合守护进程检查。我不同意所选的答案......在这种情况下,grepping 有很多潜在的陷阱。
  • 绝对不是重复的。也非常感谢你提出了一个很棒的问题。我学到了很多!对于其他人:请参阅下面关于检查其他用户会话的我的 cmets,当您需要确保其他人当前没有运行您的脚本时,通常会出现这种情况。

标签: linux bash gnu-screen


【解决方案1】:

您可以在screen -list 的输出中查找您正在检查的会话的名称:

if ! screen -list | grep -q "myscreen"; then
    # run bash script
fi

【讨论】:

  • 当然可以,但是不使用grep可以检查吗?即屏幕命令。如果您想知道会话“abcd”是否存在但只有会话“abcdefgh”,您的条件会说是,而实际上不存在。
  • 可以修改grep命令。 grep -q '^abcd$' 将仅匹配确切的会话名称“abcd”。
  • 仍然看起来不起作用,因为“^abcd$”是一个正则表达式匹配仅包含“abcd”的行。你的回答没问题。我的问题是,如果存在具有特定名称的会话,屏幕是否支持返回 0 的功能,否则不支持 0
  • 虽然我真的很喜欢 -Q select myWindow 的想法(也检查特定窗口)...这个 grep 方法是其他用户最容易检查会话的方法:if (screen -ls user/ | grep -q '\.mySession\s');
【解决方案2】:

您可以查询特定会话的屏幕“选择”命令;如果会话存在,则 shell 结果为“0”,如果未找到命名的屏幕会话,则为“1”:

$屏幕-S Tomcat $ 屏幕 -S Tomcat -Q 选择 . ;回声$? 0

对比:

$ 屏幕 -S 码头 -Q 选择。 ;回声$? 未找到屏幕会话。 1

请注意,select 之后的 '.' 是可选的,但可能更健壮。

【讨论】:

  • 是否有关于 -Q 参数作用的文档?我的 Screen (Ubuntu 12) 版本似乎没有它,这让我想知道这是非标准的还是在不同的版本上有不同的别名。
  • 即使是 Debian 上的 screen 手册页也没有提到它,它确实有效。
  • 嗯,在 Fedora 22 上,使用屏幕 4.03.01,手册页确实提到了 Q 命令和可以查询的命令。我不确定我在哪里找到关于“。”的花絮。在选择语句中...
  • 对我来说screen -S Tomcat -Q echo ''; echo $? 也可以,但不会触发重绘。
  • 它适用于我的一个系统(屏幕版本 4.03.01),而不适用于另一个系统(4.00.03)。
【解决方案3】:

鉴于我无法发表评论,我将其发布为新答案。 troyfolger 的回答是一个好主意,基本上相当于尝试向会话发送一个几乎没有什么作用的命令。一个问题是某些(旧)版本的 screen -Q 不受支持,因此对于这些版本,正确的命令是

screen -S Jetty -X select . ; echo $?

发送命令“选择”。到名为“Jetty”的屏幕会话。

选择更改哪个窗口处于活动状态并且 .表示当前活动窗口,因此这意味着尝试将活动窗口更改为当前活动窗口。如果没有我们想要的会话可以连接,这只会失败。

如果您阅读了信息文档,那么它确实建议您只使用 select 。与 -X 一起作为测试或确保选择了某些东西。

【讨论】:

  • 嗯...我坚持使用-Q! :^] 这可能是由于屏幕版本的不同。我认为旧版本的屏幕没有 Q(查询)选项,因此您不得不求助于使用 X 选项(将命令发送到屏幕)。以下是屏幕 4.03.01 手册页中的相关信息: -Q 现在可以使用此标志从远程会话中查询某些命令,例如“屏幕-Q 窗口”。这些命令会将响应发送到查询过程的标准输出。如果命令中有错误,则查询过程将以非零状态退出。
  • 我不会投反对票,但您可以将您的答案修改为“旧版本的屏幕需要 'X' 而不是 'Q' ...”
【解决方案4】:

所有提议的解决方案都不处理没有独特模式的屏幕名称,例如“测试”和“TEST123”。当您screen -S "TEST"screen -list "TEST" 时,您可能会发现自己选择了屏幕“TEST123”! GNU 屏幕实现屏幕名称匹配的方式存在问题(非确定性)。

下面是一个 bash 函数,它尝试进行完全匹配,并返回 PID.SCREEN NAME 以及退出代码:

function find_screen {
    if screen -ls "$1" | grep -o "^\s*[0-9]*\.$1[ "$'\t'"](" --color=NEVER -m 1 | grep -oh "[0-9]*\.$1" --color=NEVER -m 1 -q >/dev/null; then
        screen -ls "$1" | grep -o "^\s*[0-9]*\.$1[ "$'\t'"](" --color=NEVER -m 1 | grep -oh "[0-9]*\.$1" --color=NEVER -m 1 2>/dev/null
        return 0
    else
        echo "$1"
        return 1
    fi
}

用法 - 选择一个屏幕:

target_screen=$(find_screen "SCREEN NAME")
screen -S "$target_screen" ...etc...

用法 - 测试屏幕是否存在:

if find_screen "SCREEN NAME" >/dev/null; then
    echo "Found!"
fi

无论如何,这将涵盖 99.9% 的情况。 99,99% 确定,在屏幕名称中转义 grep 特殊字符。完美匹配需要 grep 匹配整行直到 $,包括括号中的日期,可能会随着版本的变化而变化。另一种完美匹配方法是:

ls -A -1 /var/run/screen/S-${USER} | grep "^[0-9]*\.SCREEN NAME$"

但这很麻烦,我们需要确保屏幕实现使用此文件夹。我不推荐最后一种方法。

【讨论】:

  • 一个更简单的解决方案 if screen -ls TEST|grep -q '\.TEST\s';然后回显“测试存在”;菲
【解决方案5】:

更简单的方法是:

screen -xR -S SessionName

复制自 hereStéphane Chazelas 评论:

如果没有要附加的内容,我通常使用 -xR 附加或创建。

这样您就不必搜索会话名称是否已经存在,如果存在,此方法将附加到会话,如果不存在,则创建它。

【讨论】:

    【解决方案6】:

    %100 工作。

    screen -list | grep "SESSİON NAME" && echo "Active Program" || echo "Passive Program"
    

    【讨论】:

      猜你喜欢
      • 2014-10-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 2020-03-10
      • 1970-01-01
      相关资源
      最近更新 更多