Команда запуска zsh, если процесс запущен

Я хочу получить информацию от cmus-remote если cmus бежит

#!/bin/zsh

pgrep cmus>& /dev/null
if [ $? -eq 0 ]; then
  title=$(cmus-remote -Q | grep tag | grep title | sed 's/tag title //')
  artist=$(cmus-remote -Q | grep tag | grep " artist " | sed 's/tag artist //')
  album=$(cmus-remote -Q | grep tag | grep " album " | sed 's/tag album //')
  track=$(cmus-remote -Q | grep tag | grep tracknumber | sed 's/tag tracknumber //')
  echo $track $title - $artist - $album
else
  echo ""
fi

вывод для запущенного cmus правильный, когда cmus не работает, я получаю

cmus-remote: cmus is not running
cmus-remote: cmus is not running
cmus-remote: cmus is not running
cmus-remote: cmus is not running
-

У меня есть обходной путь, добавив >& /dev/null в каждой соответствующей строке, но это не то, что я хочу, я бы хотел, чтобы код вообще не выполнялся. И я не делаю вывод из другого случая.

3 ответа

Решение

Реальная проблема, с которой вы, похоже, сталкиваетесь, заключается в том, что ваш pgrep возвращает удар, а вы этого не ожидаете.

pgrep cmus>& /dev/null
if [ $? -eq 0 ]; then
  //statements here are not evaluated if pgrep\'s exit status is not equal to 0

Ваш код выхода pgrep = ноль. но это, вероятно, не точное совпадение (cmus), которое было найдено. Попробуйте сузить область поиска с помощью pgrep (т. Е. С помощью флага u или x)

Совет: запустите ваш bash-скрипт с ключом -X, чтобы увидеть, что на самом деле был код выхода, и сравнить его с документированными кодами выхода на https://linux.die.net/man/1/pgrep

pgrep cmus>& /dev/null
if [ $? -eq 0 ]; then
  title=$(cmus-remote -Q | grep tag | grep title | sed 's/tag title //') > /dev/null 2>&1
  artist=$(cmus-remote -Q | grep tag | grep " artist " | sed 's/tag artist //') > /dev/null 2>&1
  album=$(cmus-remote -Q | grep tag | grep " album " | sed 's/tag album //') > /dev/null 2>&1
  track=$(cmus-remote -Q | grep tag | grep tracknumber | sed 's/tag tracknumber //') >/ dev/null 2>&1
  echo $track $title - $artist - $album
else
  echo ""
fi

Добавление > /dev/null 2>&1

2 относится ко второму файловому дескриптору процесса, т.е. stderr,

> означает перенаправление.

&1 означает, что цель перенаправления должна быть в том же месте, что и первый дескриптор файла, т.е. stdout,

Таким образом, эта команда сначала перенаправляет стандартный вывод /dev/null а затем перенаправляет туда stderr. Это эффективно заглушает весь вывод (обычный или с ошибкой).

В твоем случае cmus-remote: cmus is not running является stderr поэтому перенаправление, которое вы должны использовать, должно быть в состоянии перенаправить оба STDOUT а также STDERR

Лучший авторитет в том, cmus работает ли cmus-remote может получить любую информацию cmus-remote, Таким образом, вы можете просто заменить pgrep cmus с cmus-remote как это выйдет с кодом возврата 1, если cmus:

cmus-remote >& /dev/null
if [ $? -eq 0 ]; then
   # stuff
fi

В качестве альтернативы вы можете отказаться от проверки заранее и уменьшить количество вызываемых внешних команд. Просто попробуйте разобрать вывод cmus-remote -Q и игнорировать вывод на stderr:

#!/bin/zsh

cmus-remote -Q 2> /dev/null | awk '
BEGIN {
  tags["album"] = "";
  tags["artist"] = "";
  tags["title"] = "";
  tags["tracknumber"] = ""
}

$1 == "tag" && $2 in tags { 
  tag=$2;
  $1=$2="";
  sub(/  /,"");
  tags[tag] = $0
}

END {
  if (tag)
    printf "%s %s - %s - %s\n", tags["tracknumber"], tags["title"], tags["artist"], tags["album"];
  else
    print ""
}'

Это звонки cmus-remote только один раз и трубы stdout в awk (также вызывается только один раз). Если cmus сообщение об ошибке не будет передано /dev/null, awk затем анализирует вывод cmus-remote -Q и создает желаемый результат. Если cmus не запущен или если тегов не было, будет выведена пустая строка.

Другие вопросы по тегам