Bash: Как присвоить выходные данные команды, заканчивающейся ошибкой сегментации, переменной - PullRequest
0 голосов
/ 23 сентября 2018

Я использую небольшую программу, написанную кем-то еще на bash, которая работает в соответствии с cron на моем Synology NAS, и в основном она выполняет поиск субтитров для моей коллекции фильмов и, при необходимости, преобразует их кодировку в utf8.

В общем случае основной скрипт bash вызывает других подписчиков, и, к сожалению, он не работает на 100%, как следует.Во время моего исследования я сузил проблему, связанную с этой конкретной функцией в одном из индексов:

subs_getCharset_SO() {
local file="$1"
local charset=
local et=

tools_isDetected "file" || return $G_RETFAIL

et=$(file \
    --brief \
    --mime-encoding \
    --exclude apptype \
    --exclude tokens \
    --exclude cdf \
    --exclude compress \
    --exclude elf \
    --exclude soft \
    --exclude tar \
    "$file" | wrappers_lcase_SO) || {
    return $G_RETFAIL
}

case "$et" in
    *utf*) charset="UTF8";;
    *iso*) charset="ISO-8859-2";;
    us-ascii) charset="US-ASCII";;
    csascii) charset="CSASCII";;
    *ascii*) charset="ASCII";;
    *) charset="WINDOWS-1250";;
esac

echo "$charset"

}

Оказывается, что выполнение команды file для каждого файла фильма всегда вызываетОшибка сегментации.Я воспроизвел ее, запустив эту команду в терминале вручную:

admin@Synek:/volume1/video/Filmy/Ghostland.2018$ file --brief --mime encoding Ghostland.2018.txt

Вывод:

utf-8
Segmentation fault

Так что моя главная проблема, как мне кажется, заключается в том, что вывод fileкоманда не назначена переменной et.В идеале моей целью было бы захватить первую строку вывода и присвоить ее переменной et.Или, по крайней мере, перенаправить вывод в файл, поэтому я попробовал некоторые решения, которые я нашел в Интернете:

admin@Synek:/volume1/video/Filmy/Ghostland.2018$ { file --brief --mime-encoding ./Ghostland.2018.txt; } 2> log

, который выводит на терминал только нужную мне строку и пропускает сообщение об ошибке сегментации:

utf8

Запуск:

admin@Synek:/volume1/video/Filmy/Ghostland.2018$ cat log

Дает:

Segmentation fault

Но я просто не могу найти способ получить первую строку до того, как написана ошибка сегментациив выходной файл журнала.

Любая помощь приветствуется!

1 Ответ

0 голосов
/ 23 сентября 2018

Когда stdout для TTY, GNU libc (как и большинство реализаций) настраивает буферизацию строки по умолчанию, поэтому выходные данные, записанные с помощью стандартной библиотеки C, печатаются всякий раз, когда завершается полная строка (поскольку предполагается, что человек наблюдает ихочет видеть результаты, как только они будут доступны, даже если это приведет к увеличению времени выполнения).В отличие от этого, когда stdout относится к FIFO или файлу, для большей эффективности используется больший выходной буфер.

Поскольку SIGSEGV не позволяет программе очищать свои буферы, это означает, что данные все еще находятся вбуфер в момент сбоя теряется.

В системе с GNU coreutils вы можете настроить небуферизованный или линейно-буферизованный стандартный вывод (по умолчанию программы могут его переопределить), используя инструмент stdbuf:

result=$(stdbuf -o0 file --brief --mime-encoding ./Ghostland.2018.txt)

... или в системах без coreutils GNU, но с установленным expect вы можете использовать инструмент unbuffer:

result=$(unbuffer file --brief --mime-encoding ./Ghostland.2018.txt)

См. BashFAQ # 9 для получения дополнительной информации о буферизации и управлении ею из оболочки.

...