sh
shell programming
spam-chek 0.3: Быстрее, больше, сильнее
Я уже выкладывал и писал предыдущие версии скрипта spam-check. Сегодня же, в преддверии Нового 2010 года, хочу поделиться новой, третьей версией данного скрипта.
Напомню, скрипт предназначен для проверки своих (и не только) серверов на их наличие в черных списках (DNSBL).
Демотиваторы
Все мы знаем ныне популярный формат картинок в интернете - демотиваторы. Известен так же и бум , связанный с ними. Программы для создания демотиваторов были написаны на огромном множестве языков программирования. Но линуксоид во всем и всегда должен быть первым =) Внесу свою скромную лепту. Создаем демотивационные постеры одной командой при помощи скрипта!
Пишем альтернативный поиск по истории переписки в Pidgin
Итак, для начала скажу что я меньше месяца в линуксе, и естественно, пока что ламер. Поэтому предоставляю не столько код, сколько идею.
Многие мои знакомые (да и я сам) недовольны странно реализованным способом поиска в истории по ключевым словам. Хочется чего-то более удобного.
Этот элементарнейший bash-скрипт позволяет нам автоматически проискать всю историю переписки с определенным человеком, сгенерировать на ее основе HTML документ содержащий строки с искомым ключевым словом и открыть его для просмотра. Я не хотел публиковать этот позор, но друзья сказали, что это очень удобная штука...
Пользуйтесь, делайте что хотите, изменяйте, улучшайте, доведите до ума, делайте из фекалий кондитерское изделие. :) Критика приветствуется, улучшения КРАЙНЕ приветствуются. Особая просьба пофиксить костыль в коде, он заметен. А все от незнания.
timeout: запуск команды с таймаутом по истечении которого команде посылается сигнал
интересный и очень полезный скрипт нашел в документации к башу
запуск команды с таймаутом. по истечении которого команде посылается сигнал. например -9
$0 [-signal] [timeout] [:interval] [+delay] [--] <command> SIG=-TERM # default signal sent to the process when the timer expires timeout=60 # default timeout interval=15 # default interval between checks if the process is still alive delay=2 # default delay between posting the given signal and # destroying the process (kill -KILL)
редирект STDERR в пайп
В баше на первый взгляд нельзя отправить поток STDERR через пайп в другую программу. По крайней мере нельзя просто добавить '2' к операторам '|' и '>()'.
Но на самом деле это делается очень просто:
$ ./command 2>&1 >log_normal | tee log_errors | mailДело в том, что операторы редиректа обрабатываются с конца команды. Таким образом, в данном случае сначала stdout будет перенаправлен в файл log_normal, затем stderr будет скопирован в stdout.
Команда
$ ./command >log_normal 2>&1 | tee log_errors | mailЗапишет в log_normal сообщения и из stdout и из stderr, а в log_errors не попадет ничего.
Подобная запись может быть полезна при запуске скриптов из крона, когда лог хочется сохранить в файле, а ошибки - и сохранить в файл, и получить по почте.
PS
Подробнее здесь
Замер веса всех JPG в каталоге.
$ du -csh *.jpg | tail -1(c) ramok
Ссылка: 10 трюков в командной строке, о которых вы не знали. Честное слово.
10 трюков в командной строке, о которых вы не знали. Честное слово.
Рекомендую так же почитать коментарии, так как в статье не всегда оптимально.
via nexus
Очистка временых файлов в shell-скриптах
Допустим у вас есть shell-скрипт который создаёт временные файлы, именованые пайпы и прочие вещи которые необходимо очищать перед окончанием скрита.
Но если пользователь прервал работу вашего скрипта (например по ctrl-c), то в системе останется мусор.
Проблема решается регистрацией обработчика сигнала EXIT. Например
#!/bin/sh TMPFILE=`mktemp` trap "rm -f $TMPFILE; echo процедура очистки 1>&2" EXIT # ....
Когда скрипт закончится (не зависимо от того закончится он нормально или пользователь его прервёт), обработчик удалит временный файл и выведет отладочное сообщение.
Грубо говоря это аналог C-шной фунции atexit() или C++-шного деструктора класса (только для всего скрипта).
обработка аргументов с помощью getopts в конце строки
Бывает так, что нужно создать скрипт, при вызове которого дополнительные аргументы командной строки должны идти в конце. Например, чтобы
$ ./script action -o a -p -t argumentвыполнял действие action, при этом обрабатывая аргументы -o -p -t, но при
$ ./script -o a -p -t action argumentвыводил справку по использованию. (По такому принципу работает ряд утилит; в частности - многие распределённые системы контроля версий - git, mercurial, bazaar и т.п.)
Традиционно, для обработки аргументов используется утилита getopts; в Сети также можно без проблем найти множество примеров её использования.
Приблизительный пример же того, что нужно нам:
#!/bin/bash #... USAGE="script <action> <options> [file | directory]"; case "$1" in #обрабатываем действие, которое предусмотренно скриптом action1 | action2 ) action="$1" ;; #в противном случае выводим справку по использованию
Защита от случайной перезаписи содержимого файла
Защита от случайной перезаписи содержимого файла.
Любой знающий основы шела знает как можно создать файл с помощью перенаправления ввода/вывода
$ echo какой то текст > test.txt $ cat test.txt какой то текст
Но если в файле test.txt был не пустой то содержимое файла перепишется, и восстановить его уже не удастся.
В bash от такого можно защитится с помощью установки опции set -o noclobber
$ set -o noclobber $ echo другой текст > test.txt bash: test.txt: не могу переписать уже существующий файл $
Если вы знаете что делаете, и хотите переписать файл то можно или отменить эту опцию или воспользоваться специальной формой перенаправления >|
$ set +o noclobber #или $ echo тест >| test.txt
В zsh аналогичные опции выглядят так
$ setopt clobber $ setopt noclobber
И кроме привычного >| есть другая форма >!
$ echo тест >! test.txt $ echo тест >| test.txt
Имена файлов в переменных баша
Возьмите себе за правило заключать значения переменных в которых храняться имена файлов или путей в кавычки. Таким образом будут поддерживаться пути и имена файлов в которых содержаться пробелы.
#!/bin/sh for i in "$@"; do echo "$i" done
то вывод у комманды
./script.sh my\ files/*
будет адекватный. если попробовать без кавычек то работать будет криво. можете попробовать. :-)
bash reminders
я постоянно забываю как записывается в bash выражения типа : вырезать из переменной кусок строки до первого символа "такогото". поэтому пользуюсь sed, либо ищу в тырнете доку по этому поводу.
А тут наткнулся на свод всех правил в табличках. Так как я очень люблю такие таблички то и предсталяю их вам по линку.
создание собственных стартовый скриптов в debian
для написания стартовых скриптов в debian по совету ramok можно использовать темплейт /etc/init.d/skeleton, предварительно прочитав /etc/init.d/README
Как узнать размеры терминала в скрипте
Иногда полезно узнать размеры терминала в котором работает ваш скрипт (например при использовании dialog).
0. По умолчанию терминалы под X-Window устанавливают размеры терминалов в переменные LINES и COLUMNS.
Но к сожалению в скрипты они не экспортятся Ж:-(
1. Можно воспользоватся программой stty, если она поддерживает параметр size
$ stty size 71 159 $ eval `stty size | sed -e 's/\(.*\) \(.*\)/LINES=\1 COLUMNS=\2/'` $ echo $LINES $COLUMNS 71 159 $
2. Если на машине установлен ncurses (а сейчас сложно тайти машину на которой он не стоит Ж:-)
то можно воспользоваться программой tput.
COLUMNS=`tput cols` LINES=`tput lines`
3. Если на машине установлен X-Window, то можно воспользоваться командой resize которая возвращает
код на sh для установки переменных LINES и COLUMNS.
$ resize COLUMNS=159; LINES=71; export COLUMNS LINES; $ eval `resize` $ echo $LINES $COLUMNS 71 159 $
Маска для дот-файлов
Иногда возникает необходимость скопировать все файлы настройки из домашней директории (так называемые дот-файлы, так как они начинаются с точки) куда нибуть в другую директорию или залить на другую систему. Казалось бы чего проще?
cp -r .* backup-dirТо есть .* говорит "любое имя файла или директории начинающиеся с точки". Но тут есть подвох. Дело в том что в каждой директории есть две директории с именами . и .., что обозначает "текущая директория" и "родительская директория" соответсвенно.
cp -r .??* backup-dirТо есть .??* говорит "любое имя файла или директории начинающиеся с точки и содержащая не меньше двух символов". Хотя конечно эта маска не охватывает файлы короче трех символов. Лично я часто пользуюсь этой маской, потому что она применима для большинства случаев и короткая Ж:-)
Спасибо darkk-у, подсказал правильную sh маску .[^.]*
Самая правильная маска для этого выглядит в zsh так:
cp -r .*~(.|..)(^@) backup-dir.* "все файлы начинающиеся с точки"
~ "отрицание,все маски что идут после ~ не влючены в результат"
(.|..) "имя файлов . или .."
(^@) "не символические ссылки"
ну или еще более правильная для копирования дот-файлов из домашней директории
cp -r ${HOME}/.*~${HOME}/(.|..)(^@) backup-dirPS
как это выглядит в bash?
Цифровые аргументы для dd в шеснадцатиричном виде
Как ни странно утилита dd не поддерживает цифровые аргументы в шеснадцатиричном виде, хотя часто бывает нужно указать смещение или размер блока в более удобном для этого шеснадцатиричном виде. Более того в зависимости от аргумента, если передать число в шеснадцатиричном виде, в С нотации, то dd может или закончится ошибкой или проинтерпретировать как 0. Например:
$ dd bs=0x1 dd: неверный номер `0x1' $ dd count=0x1 0+0 записей считано 0+0 записей написано скопировано 0 байт (0 B), 1,248e-05 секунд, 0,0 kB/s
Запуск команды climm во всех аккаунтах
К сожалению встроенной возможности запускать команду climm во всех аккаунтах climm нет, но можно дописать необходимое Ж:-)
1. Качаем скрипт
$ wget http://linsovet.com/files/climm-global-cmd.txt -O climm-global-cmd2. Копируем его в директорию ~/bin и даем право на исполнение
$ cp climm-global-cmd ~/bin && chmod +x ~/bin/climm-global-cmd3. В любимом редакторе изменяем в скрипте переменную CONN_NUM в которой нужно через пробел перечислить все соединения в которых мы хотим выполнять команды.
Номера соединений можно подсмотреть в climm командой conn.
4. В climm создаем алиас 'g' (от "global") в котором вызываем скрипт и не забываем сохранится.
climm> alias auto g !~/bin/climm-global-cmd climm> save
5. Используем макрос. Например перейдем во всех аккаунтах в away
climm> g awayПосмотреть кто в онлайне во всех аккаунтах
climm> g eВертикальная конкатенация файлов
Склеивание столбцов данных из файлов 1.txt и 2.txt, с разделителем пробел, производится командой:
$ paste -d " " 1.txt 2.txt > 3.txt $ cat 1.txt 1 1 2 2 3 3 $ cat 2.txt 4 5 6 $ cat 3.txt 1 1 4 2 2 5 3 3 6
Либо можно сделать так:
$ paste -s -d " " 1.txt 2.txt > 3.txt $ cat 3.txt 1 1 2 2 3 3 4 5 6
Статья взята отсюда http://www.opennet.ru/tips/info/1460.shtml
Сколько строчек в файле?
Так как узнать сколько строк в файле? Как всегда в Unix есть множество способов это узнать Ж:-)
ramok@~/ wc -l .zshrc 724 .zshrc ramok@~/ cat .zshrc | wc -l 724 ramok@~/ sed -ne '$=' .zshrc 724 ramok@~/ awk 'END{print NR}' .zshrc 724 ramok@~/ grep -c "" .zshrc 724 ramok@~/ printf "G\n=\n" | ed -s .zshrc 2> /dev/null 724
Использование команды перенаправления без команды
В sh совместимых шелах есть такая возможность создавать файлы пустого размера или обнулять существующие:
# если файла tmp.txt не существовало, создается файл нулевого размера sh% ~/ > tmp.txt sh% ~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 0 2007-06-09 11:33 tmp.txt # если файл tmp.txt существовал, то файл обнуляется sh% ~/ echo 123 > tmp.txt sh% ~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 4 2007-06-09 11:33 tmp.txt sh% ~/ > tmp.txt sh% ~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 0 2007-06-09 11:33 tmp.txt
В zsh это идея, как всегда, более развита Ж:-)
Существуют переменные окружения NULLCMD и READNULLCMD,
по умолчанию установленные в cat и more соответственно.
Что позволяет такие дополнительные возможности:
# аналог cat > tmp.txt. ничего не вводим, сразу жмем ctrl-d # получаем файл нулевого размера. ramok@~/ > tmp.txt ^D ramok@~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 0 2007-06-09 11:33 tmp.txt # аналог cat > tmp.txt. вводим то что нужно внести в файл и жмем ctrl-d ramok@~/ > tmp.txt 123 ^D ramok@~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 4 2007-06-09 11:33 tmp.txt # аналог cat >> tmp.txt. вводим то что нужно добавить в файл и жмем ctrl-d ramok@~/ >> tmp.txt 456 ^D ramok@~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 8 2007-06-09 11:33 tmp.txt # аналог more < tmp.txt ramok@~/ < tmp.txt 123 456
Естественно можно установить NULLCMD и READNULLCMD в свои значения, например в
true и less соответственно. Или придумать что-нибудь лучшее Ж:-)
PS
и кой чего в нагрузку Ж:-)
в шеллах есть встроенная команда :, аналог команда true, которую тоже
можно использовать для создания/обнуления файлов более коротким способом,
чем echo -n > файл:
ramok@~/ :> tmp.txt ramok@~/ ls -l tmp.txt -rw-rw-r-- 1 ramok ramok 0 2007-06-09 11:33 tmp.txt




