Network namespeces, resolv.conf и прочие файлы конфигурации.

Когда писал заметку о сетевых неймспейсах, т.е. о том, как на одном компьютере с одной физической сетевой картой организовать несколько виртуальных сетевых интерфейсов с разными IP (копия), забыл упомянуть о маленьком, но важном моменте.

Все созданные виртуальные сетевые стеки, а эмулируется не только сетевая карта, но и весь стек вместе с маршрутизацией, правилами IPTABLES и т.д., можно и нужно по разному конфигурировать. И, естественно, есть возможность создать разные файлы конфигурации для разных namespaces.

Файлы конфигурации хранятся в каталоге /etc/netns/<имя_namespace>

Различный resolv.conf для разных namespace’ов.

Например, в основном неймспейсе есть файл /etc/resolv.conf в котором прописаны адреса DNS для основной системы:

nameserver 10.10.0.1
nameserver 10.10.0.200

И пусть в системе существует второй namespace с именем linkns и для него надо прописать DNS от Google (8.8.8.8 и 8.8.4.4):

1. Создаем каталог /etc/netns/linkns.
2. В каталоге создаем (или копируем готовый из /etc) файл resolv.conf.
3. Записываем в файл новые адреса DNS:

nameserver 8.8.8.8
nameserver 8.8.4.4

Аналогично можно поступить и с другими файлами конфигурации, например правилами IPTABLES (если ваша система поддерживает конфигурацию фаервола через конфигурационные файлы).

Grep и awk для Windows

Понадобилось тут на винде работать с некоторыми логами. И Линукса под рукой не было, нашел, в общем grep и awk под винды, вроде, из официального SourceForge GNU.

Правда, официальные версии сделаны кривовато, в том смысле, что когда хочешь скачать только бинарники, в архиве оказываются только EXE (плюс куча ненужного мусора), но не оказалось DLL, которые нужны экзешникам. Скачиваешь инсталлер — он ставит и EXE и DLL, но в PATH надо каталог вручную добавлять.

В общем, я все это дело перепаковал, в обычный RAR SFX архив, который распаковывается в %WINDIR% (обычно C:\Windows), никакого инсталлятора/анинсталлера не приделывал, и вообще это для себя и стаи товарищей. Хотите качайте, хотите нет.

Содержимое архива:

awk.exe
egrep.exe
fgrep.exe
gawk-3.1.6.exe
gawk.exe
grep.exe
libiconv2.dll
libintl3.dll
pcre3.dll
pgawk-3.1.6.exe
pgawk.exe
regex2.dll

Работает в Windows 7 x86, Windows 7 x64 и в Windows XP. В десятке, наверное, работает, но я не проверял.

Скачать grep+awk для Windows

GNU grep 2.5.4
GNU Awk 3.1.6

C mega.nz

В любом случае, прикольно, что эти утилиты под винду есть. Иногда в винде их не хватает.

Запись с экрана в Slackware Linux

Преамбула

Итак, продолжаем разбираться с записью с экрана в Linux.
Для начала, я почитал обзор Losst на соответствующие программы, и вот, что имею сказать:

RecordMyDesktop — кривой и глючный, пропускает кадры, пишет только в формате OGV, который ни одна собака не поддерживает.

Vokoscreen — не собрался, не смог найти файл своего же исходника, хотя и файл был и права на месте.

ScreenStudio — для потокового видео, мне лично не подходит.

Kazam ScreenCaster — нет возможности записи конкретного окна или произвольной области экрана.

Byzanz-record — только командная строка (да, хочу программу с графическим интерфейсом для работы с видео).

VLC Media Player — записывает, но опять же, весь рабочий стол

OBS — вообще не про «запись с экрана», а про стриминг, так что если там запись с экрана и есть, то в качестве приятного бонуса, для простой записи с экрана, это из пушки по воробьям.

Так что остановился на Simple Screen Recoder.

Установка Simple Screen Recoder

В Slackware он штатно устанавливается через sbopkg, вводим в поиске ssr и ставим, из зависимостей нужен ffmpeg.

Работа с программой

Программа простая и удобная, выполнена в виде мастера, так что работа не доставляет никакого геморроя.

На первом шаге выбираем, что будем записывать — весь десктоп, произвольную область экрана или конкретное окно, или записывать, следуя за курсором. Можно записывать и OpenGL’ные игры. Также можно включить запись звука и записывать или убрать из записи курсор.

На втором шаге выбираем кодек и формат файла, основные форматы следующие:

MKV (Кодеки H.264, VP8, Theora)
MP4 (H.264)
WebM (VP8)
OGG/OGV (Theora)

Также выбираем файл, в который будем писать, и отрубаем пропуск кадров.
Писать лучше в MP4, т.к. его любой видеоредактор поддерживает.

Можно в списке кодеков и форматов выбрать Other… и будет доступна тонкая настройка контейнера (формата файла) и кодека.

На третьем шаге включаем запись и сворачиваем программу (она спрячется в трей).

Ошибка Codec H.264 (not installed)

Причины ошибки:

1. Кодек не установлен, заходим в sbopkg и устанавливаем пакеты:

aom (выбираем multimedia/aom в меню sbopkg)
libass
libwebp
x264 (выбираем multimedia/x264 в меню sbopkg)
x265
ffmpeg4

Перезапускаем программу, если ошибка повторяется, значит установлен кривой ffmpeg (а официальный пакет ffmpeg в Slackware кривой). Сносим пакет ffmpeg и устанавливаем нормальный от Alien: качать здесь

В общем, поступаем как в заметке Перекодировка OGV в MP4 и решение ошибки Unknown encoder ‘libx264’ в Slackware Linux (копия)

Все работает:

ФАНФАРЫ!

Ссылка на обзор Losst’а

Лучшие программы для записи видео с экрана Linux

Перекодировка OGV в MP4 и решение ошибки Unknown encoder ‘libx264’ в Slackware Linux.

Преамбула

Пришлось некоторое время решать проблемы с записью видео в Linux. Изначально задача была в записи видео с экрана, но в процессе решения добавились и web/ip-камеры (заодно уж), и общие проблемы с перекодировкой видео из одного формата в другой. Начнем как раз с конца, т.е. с перекодировки.

Леша уже плюнул на попытки заставить непокорную софтину записывать для начала экран в удобоваримом формате MP4, и прислал мне ролик в формате OGG (ну не OGG, OGV), чтоб я разобрался с его перекодированием во что-то более удобоваримое, т.к. не один из наших видеоредакторов формат OGV (кстати, открытый) «из коробки» не поддерживал.

В качестве видеокодека в формате OGV используется кодек Theora, а в MP4 AVC/H.264

OGG в OGV

OGG — изначально, открытый звуковой формат, разработанный как альтернатива закрытым (WMA, MP3). Через некоторое время, данный формат был расширен с добавлением поддержки видео. Но некоторые (несознательные) линуксовые программы пишут видео, а файлы создают с расширением .ogg. Линуксовому софту, типа плееров, вообще на это плевать, но линуксовому софту всегда было плевать на расширения имени файлов, а вот винде нет. Потому, если вам прислали видео в файле с расширением .ogg, то попробуйте поменять расширение на .ogv, скорее всего файл нормально откроется. В K-Lite Mega Codec Pack и в VLC для Windows поддержка, что OGG, что OGV есть точно.

Но все-таки вернемся в Slackware и к преобразованию форматов.

Дополнительные программы, кодеки, библиотеки

В связи с диким онанизмом на «авторские» «права» и зоопарком форматов видео/аудио в Линуксе преобразование одного формата в другой превращается в наркоманский квест. У нас было десять мегабайт библиотек, две сотни кодеков, пакет с разными пакетами, 200 грамм укуреных лицензий… Тьфу, к делу.

Для установки некоторых необходимых пакетов можно воспользоваться sbopkg.

Вообще, для работы с видео и аудио используется программа ffmpeg (v3), но не спешите ставить ее из «официального» репозитория Slackware, как оказалось, чтоб все заработало, пришлось переустанавливать из альтернативного.

Пока вводим в поиске и ставим:

aom (выбираем multimedia/aom в меню sbopkg)
libass
libwebp
x264 (выбираем multimedia/x264 в меню sbopkg)
x265
ffmpeg4

ffmpeg (v3) у меня уже был установлен ранее, так же из официального репозитория Slackware. А вот и зря.

Команда для перобразования

ffmpeg -i input.ogv \
       -c:v libx264 -preset veryslow -crf 22 \
       -c:a libmp3lame -qscale:a 2 -ac 2 -ar 44100 \
       output.mp4

Преобразование будет медленным, но практически без потери качества. Свои варианты параметров можете кидать в комментарии, вдруг пригодится.

Ошибка Unknown encoder ‘libx264’

Как я сказал ранее, ffmpeg из репозитория sbopkg у меня уже стоял. Сначала я подумал, что поможет его полная переустановка с пересборкой пакета (мало ли, свежеустановленные кодеки не видятся). Не помогло.

Решение нашлось здесь

В общем да, из-за голливудских уродов патентных ограничений и прочей юридической хуйни, официальный пакет ffmpeg в Slackware не включает поддержку H.264. Но, слава Великим Древним, проблему решили без нас, и даже в опциях компиляции ковыряться не нужно:

Just to clarify, you’d want the «restricted» ffmpeg that Alien Bob offers, as that includes support for various things that have patent restrictions (like x264 encoding).

Есть готовый альтернативный пакет:

Скачать
Копия на Mega.NZ (+ копия остальных пакетов)

Linux. Вывод одновременно на консоль и в файл. Команда tee.

Преамбула

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

В Linux нашлось готовое решение: команда tee

Синтаксис и краткое описание

Команда tee делает следующее — берет переданный ей от другой команды или потока команд (pipe) вывод, пишет его в файл и одновременно выводит на stdout. Вывод на stdout можно переопределить дальше, например, устроить вывод на отдельный терминал, но об этом далее.

Общий синтаксис таков:

<команда>|tee [параметры] файл1 [файл2 файл3 ...]

где:

<команда> — любая команда оболочки Linux
| — обозначение перенаправления, вывод команды <команда> передается tee
файл1 [файл2 файл3 ...] — файлы, в которые необходимо вести запись.

Простой пример

ls | tee log.txt

Выведет список файлов текущего каталога на консоль и одновременно сохранит вывод в файл log.txt

Если добавить к команде tee параметр -a, то информация будет дозаписываться в указанные файлы. Без этого параметра файлы будут перезаписаны.

Демонстрация

Чтобы не использовать какие-то команды, создадим тестовый скрипт tscript, десять раз выводящий на консоль случайное число:

#!/bin/bash

SEC=1
CTR=10

echo "Test script, write to STDOUT random number after $SEC sec."

while [ "$CTR" -ne 0 ];do
    let "CTR=CTR-1"
    printf '%x Number: %x\n' $CTR $RANDOM
    sleep $SEC
done

echo "Complete!"

Теперь в каталоге со скриптом выполним:

./tscript | tee log.txt

На экран будут выведены случайные числа, они же будут в файле log.txt

./tscript | tee -a log.txt

Аналогично, только log-файл будет дополнен новыми случайными числами.

После команды tee, вывод можно перенаправить и дальше, например, можно совместить этот пример с выводом на другой терминал (копия):

./tscript | tee ./test.log >/dev/tty4

Можно пойти дальше и скрипт сделать автономным, «демонизировать» его, тогда можем, запустив следующую команду, или использовав ее в скрипте, освободить и/или текущую консоль или запускающий скрипт для дальнейших действий:

./tscript | tee ./test.log >/dev/tty4 &

Вывод на консоль четвертого терминала (tty4):

Вывод в test.log:

Test script, write to STDOUT random number after 1 sec.

9 Number: 2378
8 Number: 2cf9
7 Number: 132c
6 Number: 4a3c
5 Number: 6367
4 Number: 3384
3 Number: 5660
2 Number: 6655
1 Number: 6141
0 Number: 1870
Complete!

Тестовый пример на GitHub

Дополнительно

Кстати, обязательно загляните, там есть дополнительные примеры использования:

1. Команда Tee в Linux: Примеры Использования (копия).

Linux, узнать текущий терминал, узнать свой терминал, узнать текущий tty.

Команда, вы будете смеяться, очень простая:

tty

Результат работы на локальном терминале (с консоли, «с клавиатуры») и «без иксов»:

/dev/tty1

Эмуляторам терминала (из иксов или PuTTY), естественно, выделяется виртуальный терминал:

Иксы:

PuTTY:

В некоторых встраиваемых системах команда tty может не работать.

Сохранить текущий tty в переменную скрипта

В переменную скрипта можно сохранить результат выполнения команды:

#!/bin/bash

CUR_TTY=`tty`
echo $CUR_TTY

Вывод (для первого случая):

/dev/tty1

Проверка на битые сектора (bad-блоки) диска в Linux.

Преамбула

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

Проверка и получение списка bad-блоков

Естественно, все команды выполняются от root или через sudo.

badblocks -v /dev/sdc2 >/tmp/badsect.txt

где:
-v — подробный вывод информации о процессе. Правда слово «подробный» здесь некоторое преувеличение. В процессе вывод будет такой:

Checking blocks 0 to 1805311
Checking for bad blocks (read-only test):

Но, без ключа -v программа будет молчать, как партизан на допросе.

/dev/sdc2 — раздел, который необходимо проверить.
/tmp/badsect.txt — куда выводить список bad-секторов.

Программка стандартная (входит в пакет e2fsprogs), так что в неурезанных дистрибутивах есть.

Служебные сообщения она выводит на stderr, так что «наблюдать» за процессом перенаправление вывода в файл не помешает

Если после окончания работы утилиты вывод такой, то все OK, битых секторов нет:

Checking blocks 0 to 1805311
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)

Примечание: Если у вас только консоль, посмотреть список разделов можно командой

ls /dev/sd*

Вывод:
/dev/sda /dev/sdb /dev/sdb1 /dev/sdb2 /dev/sdc /dev/sdc1 /dev/sdc2

Или через fdisk:
fdisk -l

Пометка найденных сбойные секторов

Чтобы ОС не могла записать данные в битый сектор.
Примечание: способ работает только на ext файловых системах (ext2, ext3, ext4)

e2fsck -l /tmp/badsect.txt /dev/sdc2

где:

-l взять список bad-блоков из файла и пометить их.
/tmp/badsect.txt — файл со списком bad-секторов
/dev/sdc2 — раздел, с которым надо работать.

Плюсы:
+ способ работает почти во всех линуксах
Минусы:
— работает только на линуксовых файловых системах (fsck не понимает ключ -l)
— если битых секторов слишком много, проще выкинуть винчестер e2fsck начинает писать, что сектор находится «вне диапазона» и не метит его.

Грязный хак, способный на некоторое время продлить жизнь жесткого диска

Внимание! Никогда, слышите, никогда так не делайте! Начав сыпаться, жесткий диск может крякнуть в любой момент, проще (и дешевле, если у вас на харде что-то кроме котофото из интернетов) купить новый хард. Меня заставили под пытками. Мне пришлось, т.к. HDD был от древнего квадраттера, работающего на линухе, и HDD требовался IDE-шный, который сейчас хрен найдешь (да, для работы я не делюсь своими IDE HDD, я жадный).

Так вот, если битые сектора кучкуются в начале или в конце жесткого диска, то возможно, глюк оттуда не расползется, так что часть с битыми секторами можно просто отрезать и пометить в gparted как unformatted

Но никогда так не делайте. Я предупреждал.

Linux. Есть ли слово в строке. Есть ли подстрока в строке.

Довольно частой задачей является узнать, встречается ли в строке какое-нибудь слово или же, в более общем случае, подстрока.
Для решения можно воспользоваться внутренними механизмами bash, но я покажу более башенезависимый способ, с помощью grep. Благо он есть практически везде, даже в каких-нибудь системах, основанных на BusyBox, а вот вместо bash может встретится и просто sh, и что-нибудь более экзотическое.

Есть ли слово в строке

Предположим, что в переменной STR имеется строка:

STR="cat lynx lion coguar"

В переменную SUBSTR запишем первый параметр командной строки скрипта ($1):

SUBSTR="$1"

Выводим содержимое переменной $STR, передаем вывод grep с нужными параметрами, а результат сохраняем в переменную-счетчик:

CNTR=`echo "$STR" | grep -w -c "$SUBSTR"`

В данной команде более всего интересны параметры grep:

-w — искать целое слово.

Примечание: Словом по умолчанию считается все, что отделено от других символов пробелом(-ами) табуляцией(-ами) или переводом(-ами) строки.

— подсчитать количество строк с нужным вхождением

Примечание: Ключ заставляет grep подсчитывать строки, а не сами вхождения, так что количество вхождений слова в строку, так посчитать не получится.

В итоге в переменной CNTR оказывается 0, если совпадений нет, и 1, если совпадение есть, остается только проверить:

if [ "$CNTR" -ne 0 ];then
    echo "Exist"
else
    echo "Not exist"
fi

Демо-скрипт на GitHub

Примеры работы:

./exist-word lion

Вывод:
Exist

./exist-word dog
./exist-word li

Вывод:

Not exist

Более общий случай: имеется ли в строке подстрока.

Под подстрокой имеется любой набор символов, идущих подряд.

Задача решается аналогично предыдущей, только из параметров grep удаляется ключ -w

Если из вышеуказанного скрипта удалить ключ -w grep‘а, то вывод будет таким:

./exist-word li

Вывод:

Exist

Т.е. теперь была найдена подстрока li (часть слова lion).

Linux shell, pipes (конвейеры) и код завершения.

Преамбула

При работе с конвейерами (пайпами, «трубами», pipe), часто возникает вопрос, как отловить ошибку, произошедшую внутри конвейера.

Суть проблемы

Для примера возьмем код, где ход загрузки файла отображается dialog’овым прогрессбаром (копия):

#!/bin/bash

FADDR="http://tolik-punkoff.com/static/test.mp3"

wget --progress=dot -O "./test.mp3" "$FADDR" 2>&1 |\
stdbuf -o0 awk '/[.] +[0-9][0-9]?[0-9]?%/ { print substr($0,63,3) }' | \
dialog --gauge "Download file from $FADDR" 10 100

Как видите, конвейер (т.е. передача вывода от одной команды другой через |), тут налицо.

Если после данной команды просто дописать echo $?, то будет видно, что результат будет 0.

И когда все в порядке:

И когда все не в порядке (в данном случае, сделан обрыв связи):

На самом деле, это происходит потому, что в переменной $? оказывается код завершения последней команды в pipe.

Решение

В современных версиях bash перед использованием контейнера, необходимо добавить команду:

set -o pipefail

В старых bash и некоторых других оболочках придется извращаться, может как-нибудь вернусь к вопросу (если для какого утюга что писать буду).

Примечание: Следует иметь в виду “безобидные” команды, которые могут вернуть не ноль.
В больших скриптах со сложными конструкциями и длинными конвеерами можно упустить этот момент из виду, что может привести к некорректным результатам.

Проверка

После добавления вышеуказанной команды в скрипт делаем тест с обрывом связи:

Или указываем в переменной $FADDR некорректный адрес:

Теперь echo $? отображает корректный код завершения.

Модификация скрипта

Скрипт на GitHub

Источник

Linux pipes tips & tricks Копия в PDF

Скачивание файла и обработка ошибок в wget. Обратите внимание!

Преамбула

Хотел, конечно, назвать как-нибудь типа «гадское поведение wget» или «уничтожение файлов wget‘ом», но остановился на этом. Добавлю ссылку в пост о кодах ошибок (копия) на этот пост.

Но на самом деле, это вроде маленькая и многим известная штука, но которой мало кто задумывается. Особенно, если использует wget в своих скриптах. Отдельно отметить это меня сподвиг тот самый скрипт, с которого я начал сегодняшний разговор о wget (копия)

Суть проблемы

Оказывается, wget создает новый файл перед закачкой. Несмотря на то, появятся там какие-то ошибки или нет, и несмотря на то, какие ошибки это будут, хоть это ошибки сервера (например 404, файл не найден), или ошибки сети (файл не удалось докачать), файл все равно будет создан. Хотя по логике, например, ошибку сервера (пусть 404) можно было бы сначала и проверить. Но wget этого не делает, если не случилась ошибка с кодом 2 (ошибка параметров командной строки или конфигурационных файлов).

На самом деле, такой подход довольно правильный, ну и правда, какая разница, почему оно не скачалось (или не сохранилось на диск в случае I/O error). И для анализа ошибок проблем меньше.

Наибольшую проблему это представляет собой тогда, когда пользователь указывает в параметрах wget ключ -O <путь к файлу>, тогда wget придется его полюбому перезаписать.

Так-то у wget есть «защита от дурака», если файл, например, file уже существует, то при следующей закачке файл file (под тем же именем) будет сохранен, как file.1, и если что, старый файл останется в целости и сохранности. Но в скриптах ключ -O удобно использовать. Не надо следить за этими номерами файлов, и вообще в скрипте, wget без ключей, один сплошной геморрой. Так что ключи используют. Но как же правильно это сделать? Да выбирать место сохранения скачанного и проверять коды ошибок wget!

Решение

Если нужно скачать файл, а уж если скачался, заменить, не скачался, оставить старый

1. Скачиваем файл во временный:
wget -O "/tmp/test.tmp" "http://example.org/test.dat"
2. Проверяем коды ошибок (здесь самый простой вариант)

if [ "$?" -eq 0 ]; then
	#Пункт 3
fi


3. Копируем скачанный файл в целевой: cp /tmp/test.tmp /home/pi/test.dat

Естественно, все имена файлов и пути меняем на свои.

Надо скачать файл. Не скачался — вернуть сообщение об ошибке

1. Скачиваем файл:
wget -O "~.data/test.dat" "http://example.org/test.dat"

2. Проверяем коды ошибок (здесь самый простой вариант). Если ошибка — завершаем работу:

if [ "$?" -ne 0 ]; then
	rm "~.data/test.dat"
	echo "Data download error!"
	exit
fi

Посмотреть размер каталога в Linux. В консоли, но интерактивно и наглядно (ncdu).

И наглядно увидеть, где засрано 🙂

Для отображения размеров каталогов (с подкаталогами), есть стнадартная утилита du, но, если честно, она не очень удобная. Гораздо удобнее ее аналог, написанный с помощью ncursesncdu

Пользоваться очень просто. Заходим в каталог, в котором хотим узнать размеры подкаталогов, и просто вызываем утилиту:

ncdu

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


Сканирование

В подкаталоги входить можно по ENTER, возврат назад по стрелке влево, клавише h или < (обычно запятая с шифтом) или по нажатию ENTER на .., как в mc. Краткая справка по ? (не забывайте нажать SHIFT), выход по q.


Отображение каталогов и их размеров

В Slackware устанавливается штатным образом через sbopkg, как в других линуксах не знаю, в Убунте и Дебиане есть в репозиториях.

Linux wget, коды возврата/завершения. Коды ошибок wget.

Раз уж пошел разговор про wget (копия), решил я заодно дополнить добрым людям скрипт какими-нибудь осмысленными сообщениями об ошибках, а для того нужны коды завершения.

Кто-то, неизвестно почему, утверждал, что в man их нет. Есть. Но пусть уж будут и тут, и мне от склероза, и мало ли кому другому, кто не любит на буржуйском читать.

Коды завершения wget

0 — OK (ошибок нет)
1 — Иная / общая ошибка (generic error code)
2 — Ошибка в параметрах командной строки или файлах конфигурации (.wgetrc или .netrc)
3 — Ошибка файлового ввода/вывода (I/O error)
4 — Ошибка сети (например, при обрыве связи)
5 — Ошибка SSL
6 — Ошибка идентификации (неправильное имя пользователя или пароль)
7 — Ошибка протокола
8 — Ошибка сервера (например, нужный файл на сервере не найден, ошибка 404)

За исключением 0 и 1, коды выхода с меньшими номерами имеют приоритет над кодами с большими номерами, когда встречаются многочисленные типы ошибок.

Linux wget, тайм-аут и повторы. «Виснет» wget при разрыве связи.

Преамбула

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

Проблема

Оказалось, скрипт вис, если пропадало соединение с сетью.
Выгрузка производилась простой командой:

wget -O "~/buh01/data/kassa01.dat" "https://example.org/mag01/kassa.dat"

Решение

Оказывается, у wget не проставлен тайм-аут ожидания, а по умолчанию, если его не проставить, wget будет ждать аж 900 секунд (15 минут). Надо, соответственно, его напрямую указать в параметре ключа -T <секунды> (--timeout=<секунды>),
Например, можно поставить вменяемые полминуты (30 с.):

wget --timeout=30 -O "~/buh01/data/kassa01.dat" "https://example.org/mag01/kassa.dat"

Т.е. вис-то, собственно wget, хотя конечно же, не вис, а терпеливо ждал. Но тут и не бухгалтеру, а даже не сильно опытному пользователю ничего не стоит принять такое поведение за то, что wget виснет при разрыве соединения.

Заодно можно указать wget‘у количество попыток для скачивания файла: -t <число> (--tries=<число>), тем более, что указание параметра -O (имя выходного файла) сбрасывает этот параметр в 1.

wget --timeout=30 --tries=3 -O "~/buh01/data/kassa01.dat" "https://example.org/mag01/kassa.dat"

Полезные ссылки

Шпаргалка по Wget. Копия в PDF

Linux dialog —infobox с «мельницей», скрашивающей процесс ожидания.

Сделал гибрид старого скрипта waiter (копия) с dialog --infobox. В infobox‘е отображается псевдографическая «мельница»

https://www.youtube.com/watch?v=o9KempHy5To

Не стал уж совсем дублировать waiter, так что никаких параметров демо-скрипт не принимает, просто отсчитывает 10 секунд, показывая псевдографическую «крутилку».

Исходник на GitHub

Linux. Удалить комментарии из файла.

Заметка от склероза. Способ ниже удаляет закомментированные, а заодно и пустые строки из файла, но не трогает комментарии в строках. Хорошо помогает почистить какой-нибудь конфиг, в котором комментариев больше, чем самих параметров, и хрен че найдешь:

grep -o '^[^#]*' file.txt > cleaned.txt

Вместо file.txt подставляем исходный файл, вместо cleaned.txt — выходной.

Нашел здесь Копия в PDF

Там есть и другие варианты решения задачи.

Замена концов строк MAC (CR, 015 OCT, 0xD HEX) на концы строк Linux (LF, 012 OCT, 0xA HEX)

Преамбула

Понадобилось для работы. Современная MacOS такие концы строк не использует, а некоторое ПО, для совместимости со старыми маками (LC II/LC III) их еще использует. И сами маки в качестве терминалов для наблюдения за датчиками погоды еще юзаются. И живые. Я на таких учился в школе.

Это же аптайам > 20 лет, хуясе. Сии компьютеры младше меня на 5 лет всего. А по характеристикам Intel 486DX 286, ну 386 в лучшем случае, а на них есть оконный интерфейс. Правда, консоли нет и коды ошибок уже не найти (а там скудные сообщения об ошибках — messagebox с кодом).

Решение

cat "file.txt" |tr '\015' '\012' >"file2.txt"

Linux. Кодирование/декодирование файлов в/из BASE64

Преамбула

Как однажды сказал мой учитель, «линукс может все, а многое еще и из коробки, надо только знать как». Вот в данном случае именно так и оказалось. Понадобилось мне массово перекодировать файлы в/из BASE64.

BASE64 это такой древний формат данных, использующийся для передачи двоичных данных по сети. В век всеобщего юникода и кучи всякого софта это не так видно пользователю, но когда все только начиналось, с передачей данных была большая жопа. Даже на «железном» уровне некоторые машины поддерживали только семибитную кодировку, а уж о софте, не поддерживающем ничего кроме великого и могучего английского языка и говорить не приходится. Т.е. любой символ кроме букв английского алфавита и цифр мог быть либо выкинут к чертям собачьим, либо невозбранно использован как служебный. Соответственно, любой бинарный файл мог каким либо софтом, например, хитровыебанным почтовым сервером, разорван в клочья при передаче из пункта А в пункт Б.

Вот и придумали умные люди, а давайте все, что не влазит в английский алфавит и цифры, будем по хитрому алгоритму заменять, таки да. На английский алфавит и цифры. Так и получился BASE64. Подобная хрень в криптографии называется «транспортная броня».

Так вот, в Linux из коробки (входит в пакет Coreutils, который есть почти везде) есть утилита, способная кодировать/декодировать BASE64. Называется она, внезапно, base64.

Кодирование

Для опытов возьмем восьмибитного Сиро Исии. Он, когда живой был, много кого брал на опыты.

base64 isia.png >isia.b64

Закодированный Сиро Исии на Pastebin

Декодирование

base64 -d isia.b64 >isia.decoded.png

Тот случай, когда суть получилась короче преамбулы.

Аналог trim() в bash/linux shell

Преамбула

Пишу небольшой скрипт, для которого надо сохранять две выбранные пользователем при предыдущих запусках скрипта опции, а при следующих запусках их восстанавливать.
Решил воспользоваться самым простым методом. Создаем рядом со скриптом 2 файла, и туда сохраняем значения опций:

echo "$OPT1" > ./option1
echo "$OPT2" > ./option2

Некрасиво, но просто.

При запуске скрипта, читаем опции обратно:

OPT1=`cat ./option1`
OPT2=`cat ./option2`

На всякий случай лучше обрезать лишние пробелы или «пустые» символы типа TAB или переводов строки. Во всяком случае, так рекомендуют во всех руководствах по программированию, и обычно, в каждом современном языке, в некотором виде есть функция trim(), которая обрезает начальные и конечные пробелы.

Оказывается, что в bash можно обрезать не только начальные пробелы, но даже начальные и конечные пустые строки. Причем решается это одной командой.

Тестовый файл и вывод его в консоль

Возьмем, например, такой тестовый файл: На PasteBin

Если мы просто выведем его на консоль с помощью команды cat "trimtext.txt", то получится следующее:

smallwolfie@wolfschanze:~/myfiles/test/trim# ./testtrim


                   Trim()

smallwolfie@wolfschanze:~/myfiles/test/trim#

т.е. со всеми пробелами и пустыми строками.

Решение

Самая простая реализация trim() в shell/bash пропустить вывод команды через xargs без параметров. xargs, которая требует после себя команды, без указания команды все равно что echo без параметров. А echo без параметров все пустое обрезает.

#!/bin/bash

cat "trimtext.txt"|xargs

Вывод:

./testtrim
Trim()

Linux dialog, прикручиваем симпатичный progressbar к wget.

Преамбула

Какой бы ваш скрипт не был диалоговым, «само дерево жужжать не может», а в скрипте обычно жужжат утилиты, которые о диалоговых окнах представления не имеют. Так вот прикрутим контролируемый прогрессбар (--gauge) из виджетов dialog к всем известному wget.

Готовый код

#!/bin/bash

FADDR="http://tolik-punkoff.com/static/test.mp3"

wget --progress=dot -O "./test.mp3" "$FADDR" 2>&1 |\
stdbuf -o0 awk '/[.] +[0-9][0-9]?[0-9]?%/ { print substr($0,63,3) }' | \
dialog --gauge "Download file from $FADDR" 10 100

Разбираем, что он делает

1. Если просто запустить wget без параметра --progress=dot (параметр -O "./test.mp3" здесь показывает путь и имя для сохраняемого файла, для теста оно у нас жестко задано), то wget попытается нарисовать свой плохенький progressbar:

Использование параметра --progress=dot приводит вывод на экран в такой вид:

Теперь у нас видны проценты, которые выводятся по штуке на строчку через определенный интервал времени по внутреннему алгоритму wget.

2. wget почему-то выводит сообщения о своей работе не на stdout, а на stderr. Аж морово поветрие какое-то, ибо и некоторые другие утилиты тоже выводят на stderr. Оправданно на stderr выводит сообщения только dialog, тому ще он всю псевдографику выводит на stdout. Отучаем wget писать на stderr вместо stdout:

2>&1

2 — зарезервированный канал для stderr 1 — для stdout. Тут мы просто перенаправляем один канал в другой.

3. Меняем буферизацию. На самом деле, буфер консоли (терминала) выводит на экран сообщение, если в буфере консоли накопилось 1024 байта. Или программа завершилась. Иначе нет. С помощью утилиты stdbuf устанавливаем буфер stdout (-o) в ноль (-o0), тем самым мы добиваемся, чтоб символы сразу поступали на вход awk. stdbuf в качестве второго параметра требует программу, которой она будет посылать измененный буфер. В данном случае awk.

buffering in standard streams
man stdbuf на русском

За разъяснение спасибо другу из Телеграм.

4. Далее вывод wget‘а передается awk, которая хитрой регуляркой и оператором substr вырезает из вывода все, кроме значений процентов.

5. dialog --gauge может принимать из stdout числа, и отображать их в виде progressbar’а

Пример на GitHub