如何检测命令是否未应答

How to detect if a command was not answered

本文关键字:命令 是否 应答 检测 何检测      更新时间:2023-10-16

我正在创建一个在终端上发送命令的程序:

cmus-remote -Q

输出:

status stopped
set aaa_mode album
set continue false
set play_library true
set play_sorted false
set replaygain disabled
set replaygain_limit true
set replaygain_preamp 6.000000
set repeat false
set repeat_current false
set shuffle false
set softvol false
set vol_left 0
set vol_right 0

此命令返回我的音乐播放器的状态 ( cmus ),但有时播放器已关闭并且不响应我的命令。

我的目标是确定何时没有得到答案并关闭程序并再次打开它(C++)。我知道如何杀死它并重新开始。我尝试使用popen()功能的东西,但我不知道如何使用它。我该怎么做?

就可以用C++编译的 C 函数而言(对标头进行适当的更改,并在适当的情况下添加using namespace std;)。 您需要查看播放器运行时来自cmus-remote -Q的状态消息 - 我假设"状态就绪",但如果有多个响应("状态正在播放","状态暂停",...),那么您需要适当地修改代码。 我还假设您只需要响应的第一行。 同样,如果这是错误的,则必须对代码进行相应的更改。

bool is_cmus_running(void)
{
    char buffer[4096];
    FILE *fp = popen("cmus-remote -Q", "r");
    if (fp == 0)
        return false;
    char *rv = fgets(buffer, sizeof(buffer), fp);
    pclose(fp);
    if (rv == 0 || strncmp(buffer, "status ready", sizeof("status ready") - 1) != 0)
        return false;
    return true;
}

对于 C99,您需要:

#include <stdbool.h>
#include <stdio.h>
#include <string.h>

对于C++,我认为您可以使用相同的标头,但您也可以使用:

#include <cstdio>
#include <cstring>
using namespace std;

(您不需要bool标头,因为它以 C 中没有的方式内置到 C++ 中。

(1)我会以更简单的方式做到这一点,除非有特定的原因坚持C++。一个基本的 shell 脚本可以完美地完成这项工作,类似于 cplay 脚本 (https://wiki.archlinux.org/index.php/Cmus#Remote_Control):

$ ps h -C cmus || cmus

由于 Cmus 不是一个真正的后台服务,例如,如果没有 ncurses GUI,您将无法启动它 - 最好是在屏幕会话中运行它。

$ screen -rD cmus || screen -dmS 'cmus' /usr/bin/cmus

使用此命令,您始终在屏幕会话中运行 cmus 会话。您甚至可以关闭终端,该服务将在后台继续运行。只需将此命令作为别名放入您的 .bashrc,您就可以始终轻松访问播放器

$ alias mycmus='screen -rD cmus || screen -dmS 'cmus' /usr/bin/cmus'

如果未运行,将启动 cmus+screen 会话,否则将打开会话。"Ctrl+a d"分离窗口。

将它们放在一起并回答您的问题(在 shell 脚本中):

将以下行添加到文件中,例如:"mycplayer.sh"(不要忘记chmod +x mycplayer.sh,然后将其添加到 PATH 中)

#!/bin/sh
cmus-remote -Q > /dev/null || screen -dmS 'cmus' /usr/bin/cmus
cmus-remote $1

第一行将确保有一个正在运行的 cmus 实例(在后台,使用屏幕),第二行将执行远程命令。

用法:

$ mycplayer.sh -u   start/stop the player
$ mycplayer.sh -n   next in the playlist
etc.

(2)在C++

  • 使用 stat(2) 检查是否有 CMUS 的套接字/home/user/.cmus/socket

  • 如果没有进程运行,请使用 exec+fork 执行它(分叉和高管的区别)

(3)如果cmus是网络服务,所以它是用--listen host[:port]启动的,那么你需要一个ssh来启动远程盒子上的服务。请参阅上面的屏幕命令如何操作。

希望这有帮助。