Командная строка и те невообразимые вещи, которые с ее помощью можно творить, — визитная карточка UNIX и всех ее наследников. А где есть командная строка, там есть скрипты. И сегодня... нет, мы не будем учиться писать скрипты, мы рассмотрим наиболее полезные из них, те, что ты сможешь применять ежедневно для решения самого разного круга задач, начиная от сводки погоды и веб-сервера в одну строку и заканчивая ботом для твиттера в десять строк и скриптом для автоматического запуска любого торрент-клиента.
Сразу оговорюсь, что я вовсе не приверженец шаманизма и ни в коем случае не призываю тебя сидеть в зелено-черной консоли и набирать кучу букв, чтобы выполнить действия, для которых в графическом интерфейсе достаточно навести мышку на нужный элемент. Однако я убежден, что для решения многих задач консоль и скрипты годятся гораздо лучше графического интерфейса и поэтому пренебрегать ими никак нельзя. Тем более что любая DE позволяет создать для скрипта иконку, так что для его запуска даже не надо будет открывать консоль.
Простые примеры
Итак, не разглагольствуя понапрасну, сразу перейдем к примерам:
$ curl ifconfig.co
Эта простая команда покажет тебе внешний IP — идеальный вариант, если в Сеть ты ходишь через роутер. Все, что она делает, — просто обращается к серверу ifconfig.co, который возвращает обратно IP-шник одной строкой вместо полноценной веб-страницы.
И да, это вовсе не скрипт, это просто команда, но, чтобы превратить команду в скрипт, достаточно поместить ее в текстовый файл и первой строкой добавить так называемый шебанг, то есть символы #!, за которыми следует имя командного интерпретатора:
#!/bin/bash
curl ifconfig.co
Далее скрипт сохраняем в каталог ~/bin и назначаем права на исполнение:
$ chmod +x ~/bin/myip.sh
Теперь его можно вызывать из командной строки командой myip.sh.
Идем дальше.
#!/bin/sh
curl -4 wttr.in/Moscow
Этот скрипт позволяет получить сводку погоды на четыре дня. Принцип тут такой же, как в случае с ifconfig.co.
#!/bin/sh
dig +short txt $1.wp.dg.cx
А так можно получить краткое описание чего-либо в Википедии, причем с помощью DNS-запроса вместо обращения к веб-серверу. Кстати, веб-сервер через командную строку тоже очень легко создать:
#!/bin/sh
while ( nc -l 80 < file.html > : ) ; do : ; done
Данный скрипт основан на утилите netcat (nc), которую называют швейцарским армейским ножом для сетевых операций. Скрипт запускает цикл, выполняющий команду nc, которая слушает 80-й порт и в ответ на запрос отдает file.html, отправляя переданный запрос в никуда (символ означает noop, то есть пустую операцию).
С помощью простых скриптов и команд можно запросто слушать интернет-радио:
#!/bin/sh
mpv --volume=50 -playlist ~/16bit.fm_128.m3u
Естественно, плей-лист в формате M3U необходимо заранее скачать с сайта радиостанции. Кстати, если запустить MPlayer с аргументом --input-ipc-server=/tmp/mpvsocket, им можно будет управлять, записывая команды в файл. Например, настроить громкость:
echo 'volume +10' | socat - /tmp/mpvsocket
Создай два скрипта: один для запуска, другой для остановки радио (со строкой killall mpv), повесь их на рабочий стол и настрой горячие клавиши DE на управление воспроизведением. Вуаля, у тебя готов плеер для интернет-радио, запустить который можно, просто кликнув по иконке на рабочем столе. И он почти не будет расходовать память или занимать трей.
Но отвлечемся от сетевых операций и вернемся к локальным делам.
#!/bin/sh
tar -czf "../${PWD##*/}.tar.gz" .
Это один из моих любимых скриптов. Он создает архив tar.gz текущего каталога. Особого внимания здесь заслуживает конструкция ${PWD##*/}
, которая берет полный путь до текущего каталога (переменная $PWD) и удаляет из него первую часть вплоть до последнего слеша, оставляя, таким образом, только имя самого каталога. Далее к нему добавляется расширение tar.gz. Более подробно о таких конструкциях ты можешь прочитать в man bash.
#!/bin/sh
while true; do
inotifywait -r -e MODIFY КАТАЛОГ && ТВОЯ_КОМАНДА
done
А это уже скрипт, который запускает команду в ответ на изменение файлов в каталоге. Ее можно использовать для множества разных целей, например для автоматического включения плеера при сохранении MP3-файла. Или просто выводить уведомление на десктоп, используя в качестве команды notify-send:
notify-send "Файл изменен"
Десктоп
Раз уж мы заговорили о десктопе, то продолжим. Как и консоль, его тоже можно заскриптовать. Вот, например, скрипт, загружающий случайные обои, опубликованные на reddit-канале wallpaper:
#!/bin/bash
wget -O - http://www.reddit.com/r/wallpaper |\
grep -Eo 'http://i.imgur.com[^&]+jpg' |\
shuf -n 1 |\
xargs wget -O background.jpg
feh --bg-fill background.jpg
Здесь все просто. С помощью wget скрипт загружает страницу www.reddit.com/r/wallpaper, передает ее grep, который ищет на ней ссылки на imgur, выбирает случайную ссылку с помощью shuf, загружает ее опять же с помощью wget и устанавливает в качестве обоев, используя команду feh (это такой миниатюрный просмотрщик изображений, его нужно предварительно установить). Скрипт можно добавить на рабочий стол, и тогда по клику у тебя будут меняться обои.
#!/bin/sh
state=`synclient | grep TouchpadOff | cut -d '=' -f 2`
if [ $state = "1" ]; then
synclient TouchpadOff=0
else
synclient TouchpadOff=1
fi
А это скрипт для включения/выключения тачпада ноутбука: включает, если отключен, и наоборот. В своей работе использует утилиту synclient, позволяющую управлять тачпадами производства Synaptics (90% тачпадов делают они). При запуске без аргументов утилита выводит различную информацию о тачпаде, в том числе строку TouchpadOff = 1, если он активирован, и TouchpadOff = 2, если отключен. Скрипт находит это значение и в зависимости от состояния тачпада включает или отключает его.
!#/bin/bash
mpv tv:// -frames 3 -vo jpeg
mv 00000003.jpg photo.jpg
rm -f 0000*.jpg
А так можно сделать снимок с помощью веб-камеры. Скрипт использует видеоплеер mpv, чтобы записать первые три кадра, снятые камерой, в JPEG-файлы с именами 0000000.jpg, 00000002.jpg, 00000003.jpg, затем переименовывает третий снимок в файл photo.jpg, а остальные удаляет. Три снимка необходимы для того, чтобы камера успела провести инициализацию, обычно первые два получаются просто черными. Иногда изображение выходит перевернутым; чтобы это исправить, mpv следует запускать с флагом -vf flip
:
$ mpv tv:// -frames 3 -vf flip -vo jpeg
Ту же самую команду можно использовать для создания полноценной камеры слежения, которая делает снимки в моменты, когда юзер прикасается к мыши:
#!/bin/bash
while true; do
sudo cat /dev/input/mouse0 | read -n1
mpv tv:// -frames 3 -vo jpeg
mv 00000003.jpg `date +%F-%H-%M`.jpg
rm -f 0000*.jpg
sleep 10
done
Скрипт входит в бесконечный цикл, ожидая данные на устройстве /dev/input/mouse0
. Если данные есть, значит, мышь сдвинулась или была нажата одна из ее клавиш. После этого он использует mpv, чтобы сделать три снимка, дает третьему снимку имя текущей даты и удаляет остальные.
Для записи полноценного видео с веб-камеры можно использовать такой скрипт:
#!/bin/bash
mencoder tv:// -tv driver=v4l2:width=800:height=600:device=/dev/video0:fps=30:outfmt=yuy2:forceaudio:alsa:adevice=hw.2,0 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=1800 -ffourcc xvid -oac mp3lame -lameopts cbr=128 -o video.avi
В результате ты получишь video.avi в формате MPEG4 с битрейтом 1800 и аудиодорожкой в формате MP3 с битрейтом 128.
#!/bin/bash
ffmpeg -f x11grab -r 25 -s 1366x768 -i :0.0 screencast.mpg
А так ты можешь записать скринкаст. 1366x768 — разрешение рабочего стола. Просто сделать скриншот отдельного окна всегда можно с помощью команды import:
import screenshot.png
После ее запуска значок мыши изменится на «прицел», с помощью которого можно выбрать окно. Повесив эту команду на клавиатурную комбинацию, ты получишь практически идеальную систему снятия скриншотов, абсолютно не жрущую память, как это делают специализированные приложения, постоянно висящие в трее.
Подключить и настроить внешний монитор тоже можно из командной строки:
#!/bin/sh
if [ -z "$1" ]; then
exit
fi
if [ $1 == "off" ]; then
xrandr --output VGA-0 --off
xrandr -s 0
else if [ $1 == "on"]; then
xrandr --output LVDS --auto --primary --output VGA-0 --auto --left-of LVDS
xrandr --newmode "1920x1080" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
xrandr --addmode VGA-0 1920x1080
xrandr --output VGA-0 --mode 1920x1080
fi
xrandr --dpi 96
Данный скрипт предполагает, что основной монитор носит имя LVDS, а внешний — VGA-0. Это стандартная ситуация для ноутбуков; если ты не уверен, можешь проверить вывод команды xrandr: при передаче скрипту аргумента off он отключает внешний монитор, аргумент on, в свою очередь, включает его, располагая по левую сторону от основного (аргумент --left-of LVDS в первой команде). Далее скрипт добавляет новую конфигурацию для монитора с разрешением 1920 x 1080 и активирует его. В самом конце скрипт устанавливает дефолтное значение DPI — как показывает практика, при подключении монитора с другим разрешением оно часто слетает.
На самом деле в большинстве случаев команды xrandr --newmode ... и xrandr --addmode ... не нужны, так как Xorg может получить конфигурацию монитора и поддерживаемые им разрешения с помощью EDID. Иногда, однако, этого не происходит, и строку конфигурации, указываемую после аргумента --newmode, приходится генерировать самостоятельно с помощью инструмента cvt:
$ cvt 1920 1080
Он же поможет сгенерировать нестандартное разрешение, «не поддерживаемое» монитором по умолчанию.
Google, Twitter, Dropbox и торренты
Отвлечемся от десктопных дел и поговорим о сетевых сервисах. Начнем, разумеется, с Google. Вот так будет выглядеть скрипт для получения первых десяти результатов поиска:
#!/bin/bash
Q="$@"
URL='https://www.google.de/search?tbs=li:1&q='
AGENT="Mozilla/4.0"
stream=$(curl -A "$AGENT" -skLm 10 "${GOOG_URL}${Q//\ /+}" | grep -oP '\/url\?q=.+?&' | sed 's|/url?q=||; s|&||')
echo -e "${stream//\%/\x}"
Скрипт делает запрос к Google с помощью уже знакомого нам curl, заменяя пробелы в поисковой строке на плюсы. Далее выискивает в ответном HTML ссылки и выводит их на экран. Все просто, хоть и кажется сложным.
Второй популярный сервис — YouTube:
#!/bin/bash
mpv -fs -quiet `youtube-dl -g "$1"`
Здесь все совсем просто. Скрипт всего лишь проигрывает видео с указанным в аргументе ID с помощью плеера mpv. Естественно, youtube-dl придется установить заранее.
Как насчет твиттера? Нет проблем, вот полноценный бот, который на входе принимает команду, выполняет ее с помощью командного интерпретатора и отправляет результат указанному юзеру.
#!/bin/bash
USER="ТВОЙ_НИК"
while true; do
CMD=`echo "/dma +1" | ttytter -script | sed 's/\[.*\]\ //'
if [ $CMD != $OLD_CMD ]; then
REPL=`$CMD`
echo "/dm $USER ${REPL:0:140}" | ttytter -script
CMD = $OLD_COMD
fi
sleep 60
done
Скрипт использует консольный клиент ttytter, читая в цикле последнее direct message, далее он проверяет, не была ли такая команда уже выполнена, и, если нет, выполняет ее и отправляет указанному в переменной USER пользователю, попутно обрезая до 140 символов.
Чтобы все заработало как надо, тебе придется установить ttytter, запустить его, ввести приведенную им ссылку в адресную строку браузера, скопировать показанный браузером ключ аутентификации и ввести его в ttytter. Естественно, перед тем как это сделать, следует завести для бота отдельного юзера и залогиниться под его учеткой.
Твиттер можно использовать не только для выполнения команд, но и для мониторинга машины. Следующий скрипт отправляет в ленту сообщение с информацией о состоянии машины (имя хоста, uptime, нагрузка, свободная память и нагрузка на CPU):
#!/bin/bash
HOST=`hostname -s`
UP=`uptime | cut -d" " -f4,5 | cut -d"," -f1`
LOAD=`uptime | cut -d":" -f5,6`
MEM=`ps aux | awk '{ sum += $4 }; END { print sum }'`
CPU=`ps aux | awk '{ sum += $3 }; END { print sum }'`
tweet="Host: ${HOST}, uptime: ${UP}, cpu: ${CPU}%, memory: ${MEM}%, loadavg ${LOAD}"
if [ $(echo "${tweet}" | wc -c) -gt 140 ]; then
echo "FATAL: The tweet is longer than 140 characters!"
exit 1
fi
echo $tweet | ttytter -script
Ну и под конец приведу скрипт, не связанный с сетевыми сервисами, но имеющий прямое отношение к сетям и к тому, зачем мы обычно их используем. Это скрипт для запуска и остановки торрент-клиента во время простоя машины:
#!/bin/bash
IDLE=600000
STOPCMD="transmission-remote -S"
STARTCMD="transmission-remote -s"
STOPPED="yes"
while true; do
if [ `xprintidle` -gt $IDLE ]; then
if [ $STOPPED = "yes" ]; then
$STARTCMD
STOPPED="no"
fi
else
if [ $STOPPED = "no" ]; then
$STOPCMD
STOPPED="yes"
fi
fi
sleep 60
done
Скрипт уходит в бесконечный цикл, каждую минуту проверяя, сколько миллисекунд прошло с момента, когда юзер что-либо делал (для этого используется команда xprintidle). Если прошло уже 600 000 мс (десять минут), скрипт выполняет команду, указанную в переменной STARTCMD. В противном случае он выполнит команду STOPCMD, но только тогда, когда до нее была выполнена команда STARTCMD. Если кратко: ничего не делаешь за компом десять минут — запускается STARTCMD, в данном случае это команда запуска всех закачек с помощью Transmission, если нет — приостановка всех закачек. Не любишь Transmission? Нет проблем, вот команды для Deluge:
STOPCMD="deluge-console pause \*"
STARTCMD="deluge-console resume \*"
Вместо выводов
Не удивлюсь, если все описанное в статье покажется тебе очередным велосипедостроением, и даже соглашусь с таким мнением. Все-таки современный Linux — это не та система для сумасшедших экспериментаторов, какой она была пятнадцать лет назад. Сегодня для каждой задачи можно найти отдельный, отлаженный и хорошо работающий инструмент, в том числе графический. Другое дело, что не совсем понятно, стоит ли захламлять систему тяжеловесными написанными на Python приложениями с кучей зависимостей, когда ту же задачу легко решить с помощью простенького скрипта.
Каким путем пойти — выбирать тебе. Встанешь ли ты на темную сторону или выберешь путь джедая?
telnet towel.blinkenlights.nl