mindsellers
72 subscribers
25 photos
8 files
32 links
Практики из жизни Linux-админа. Asterisk, Bash, Python и черная магия.

Сайт http://mindsellers.ru
Группа VK https://vk.com/mindsellers
ТыТруба https://www.youtube.com/channel/UC7LUJgzIUL4VGiOWctoa0fw
По всяким вопросам обращаться @alex_dmit
Download Telegram
Hello, World
Ну-с, приступим к наполению канала...
Попросили тут меня слить с одного компьютера все, что можно считать рабочими документами: ворды там всякие, эксели, да еще и сохранить структуру каталогов. Сказано-сделано: монтируем диск и используем черную магию find с регуляркой

find /mnt/source/ -type f -regex ".*\(doc\|docx\|xls\|xlsx\|pdf\|zip\|7z\)$" -print0 |xargs --null cp --parents -t /dest/


#onestringscript #bash
Создание случайной текстовой строки на Python

Вполне типовая задача, которую часто приходится решать админу, который хоть как-то автоматизирует свою работу. На питоне реализация очень элегантная, а учитывая что в любой современный Linux-based дистрибутив Python включен, а часто еще и в двух версиях..... В общем, ловите

  pwd = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(length)])


Итак, что значит сия волшебная строка.... Переменной мы присваиваем странное значение. На самом деле, все довольно просто: конструкция
somevar=[some_operand for n in someradge]

присвоит переменной результат выполнения some_operand по количеству проходов цикла.
В нашей волшебной строке мы присваиваем pwd нечто странное: ''.join(something)
Что это такое? - да все просто: у разных переменных(которые на самом деле объекты, но это не слишком важно), в том числе у строк, есть метод join, который просто дописывает нечто к значению переменной. Cоответственно, мы получаем некую строку сформированную в результате length случайных выборок из символов латинского алфавита и цифр. Но нам требуются два модуля, которые мы использовали:
random
string


Давайте посмотрим на пример программы:
def randpass(length=32):
import random, string
pwd = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(length)])
return pwd
print randpass(16)


Мы объявили функцию и приняли параметр length. Если параметр не задан, используем значение 32.
Далее, мы подгрузили 2 необходимых модуля, присвоили значение переменной pwd и вернули ее с помощью return. Никто не обязывает нас использовать переменную(ну, то есть объект) pwd - можно было запихнуть нашу волшебную строку в return, но читаемость предлагаемого варианта, согласитесь, выше))

Ну а дальше мы просто "дергаем" функцию с параметром 16 и получаем на stdout пароль нужной длины

#onestringscript #python #mindsellers
Как спасти сервер от коллеги и про тайну личной переписки

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

Представьте: ваш коллега потопал ножками в серверную, чтобы внести некие изменения на Linux-сервере с консоли. Ну допустим, айпишник сменить, чтобы в случае падения быстренько все на месте исправить. Или ядро обновить. Или просто он не доверяет ssh. Телефон этот раздолбай, как обычно, оставил в кабинете. И тут до вас внезапно доходит осознание того, что если он осуществит задуманное, сервер ляжет и не встанет. Как его остановить? Бежать за ним уже поздно, кричать бесполезно...

Или вот другая ситуация: вы, используя команду who видите, что на сервере есть подключенные по ssh клиенты, а сервер надобно перезагрузить. Как узнать - реально ли кто-то там что-то там делает, или просто забыл закрыть консольку? Как предупредить всех о своем намерении перезагрузить сервер?

Оказывается, в любом современном дистрибутиве есть волшебная команда wall, которая будучи вызванной с некой строкой в качестве аргумента принудительно выплюнет оную во все активные терминалы!!!

wall Hello World!

На всех консолях, даже если там что-то запущено, появится что-то вроде

Broadcast message from root@mindserllers (pts/2) (Fri Mar 23 15:28:21 2018):   

Hello World!


Вот такая полезная софтина, на которую я почему-то никогда не натыкался.

Но тут я вспомнил еще об одной давней мечте - иметь возможность обмена информацией по максимально защищенному каналу, но с людьми, для которых настройка VPN - уже целое дело. Догадываетесь, да? Просто ставим putty, даем друзьям дико кастрированный shell до какой-нибудь своей виртуалки в Цюрихе(ну, у всех ж есть виртуалка в Цюрихе, да?), - и готово, переписочка внутри ssh и не надо ничего писать самому. Да, пусть не самая удобная, но зато мы ТОЧНО знаем, что никакой Паша Дуров никакую нашу переписку никуда не сливает.

Но давайте пофантазируем дальше и решим, как все-таки кастрировать shell тем друзьям, которым удастся "продать" нашу безопасность. Да все просто: мы напишем свой shell!

Создадим файл /usr/bin/chat_shell.py с правами 755 и запишем в него

#!/usr/bin/python

import os
from getpass import getuser
user=getuser()
print 'Hello, '+user +'\n'
print 'To quit type "/exit"' + '\n\n'
try:
while True:
string=raw_input(user+'>')
if string == '/exit':
exit()
elif string == '':
pass
else:
os.system('wall'+' ' +string)
except:
pass

Это и будет наш шелл. Теперь добавим его в список командных оболочек:

echo '/usr/bin/chat_shell.py' >> /etc/shells

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

echo alias chat='/usr/bin/chat_shell.py' >> /etc/bash.bashrc

Ну и создаем ограниченного юзера:

adduser username --shell /usr/bin/chat_shell.py

Вот, собственно, и все на сегодня.

P.S. Как вы понимаете, аналогичным образом можно написать свой "ограниченный" shell практически под любые задачи.

Всем хороших выходных!

#onestringscript #python #linux
Получение уникальных строк на Bash

Еще одна простая строка, которая может помочь в разных ситуациях. Допустим, у нас есть почтовик, и тут мы замечаем, что в очереди postqueue -p довольно много писем со статусом Over quota, что говорит нам о переполнении ящиков. Надо бы предупредить пользователей, почистить ящики и так далее. Естественно, мы легко выделим список всех переполненных ящиков примерно так:
postqueue -p | grep 'Over quota' -A1 | grep '@' 

Но на выходе мы получим кучу дублированных строк, так как на переполенный ящик в списке на доставку может стоять далеко не одно сообщение. На помощь нам придут две команды - sort, которая по умолчанию отсортирует строки по алфавиту, и uniq, которая удалит из выдачи повторы. Итого, получим
postqueue -p | grep 'Over quota' -A1 | grep '@' |sort | uniq

что на выходе даст нам несколько строк с переполненными ящиками.

#onestringscript #linux #bash
VPN за 10 секунд для системных администраторов

Итак, интернет в РФ планомерно превращается в тыкву, и если для телеграма есть прокси, для сайтиков - анонимайзеры и VPN, то как быть в случае, если с удаленного сервера станет недоступно что-то важное? Например, я вот не смог плагины для OpenFire скачать на днях. Поднимать vpn-клиент на сервере и на горячую настраивать маршрутизацию - и долго, и страшно. И вообще не наш путь. Есть ж ssh!

Для решения задачи по туннелированию всего или части трафика через сервера в странах, где у власти адекватные люди, прекрасно подходит утиллита sshuttle. Рассмотрим ее установку, параметры и возможности

apt install sshuttle
sshuttle -r login@domain.xx 0/0 #заворачиваем весь трафик в ssh-туннель, кроме dns-запросов
sshuttle --dns -r login@domain.xx 0/0 #заворачиваем весь трафик, в том числе dns
sshuttle -r login@domain.xx 11.22.33.44/26 #заворачиваем только определенную сеть
sshuttle -r login@domain.xx 0/0 -x 10.0.0.0/8 #заворачиваем все, кроме указанной подсети


Обратите внимание, что для запуска sshuttle потребуются права sudo!

Естественно, можно использовать этот замечательный инструмент и для обеспечения временного доступа в локальную сеть предприятия(ну или квартиры, если у вас проброшен ssh и белый айпишник) удаленно, особенно в том случае, когда vpn-сервера нет, а делать его лень.

P.S. Знаю, что для многих sshuttle - давно известный инструмент, но я почему-то про него не знал, и думаю, что кому-то это знание будет так же полезно, как и мне.

#onestringscript #linux #bash #vpn #proxy #telegram
Выделение раздела Linux на диске без перезагрузки и LVM. Бесплатно, без СМС

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

Тут нам на помощь приходит замечательная команда:

fallocate -l 10G /tmp/disk.img


которая создаст файл размером 10 гигабайт в /tmp. Далее, с этим файлом можно обращаться как с разделом:

mkfs.ext4 /tmp/disk.img
mount /tmp/disk.img /mnt


А уж кейсы, в которых можно применить подобный подход, придумайте сами.

#linux #onestringscript
Как выгрузить список активных пользователей Zimbra

Возникла задача - получить список активных пользователей домена domain.ltd почтового сервера на Zimbra. Очевидного решения не нашел, поэтому родился нижеследующий колхоз

su zimbra #переключаемся под пользователя zimbra
cd /tmp #переходим в tmp

zmprov -l gaa -v domain.ltd | grep -B11 'zimbraAccountStatus: active' > /tmp/all #в файл выдергиваем строку с нужным статусом
# и 11 строк до нее
# блоки в файле будут разделены ---
# поэтому каждый блок в сумме будет 13 строк
split -l 13 all # разбиваем файл на отдельные, каждый по 13 строк
#файлы будут начинаться на х
for file in ./x*; do echo $(cat $file|grep display| cut -d':' -f2)';'$(cat $file|grep mail| cut -d':' -f2) ; done > csv.csv
#выводим в csv displayName и саму почту
rm -f ./x*
rm -f ./all
#удаляем ненужные файлы


На выходе получаем валидный csv-файл
#Linux #bash #onestringscript
Простой нагрузочный тест сайта

Иногда требуется оценить, с какой нагрузкой в принципе способен справиться сайт на текущий момент, оценочно и без подробностей. На помощь придет утилита Apache Bench, использование которой крайне просто

 ab -c 50 -n 1000 http://your-site.ltd 


команда выполнит 1000 запросов в 50 потоков. В выдаче, на мой взгляд, самыми важными параметрами будут

Requests per second — количество запросов в секунду
Time per request (mean) — среднее время на выполнение группы параллельных запросов

#onestringscript
Как быстро отдать внешней системе статус абонента Asterisk

Дисклеймер: так делать нежелательно по куче причин, но если надо "вотпрямсейчас" - то допустимо

Правильный путь получения статуса устройства в Asterisk - это, конечно, подключение через AMI, запрос-ответ-обработка. А еще более правильный - получение статусов всех устройств через одно обращение раз в n миллисекунд, хранение оных и отдача их внешним потребителям уже без "дергания" астера.
Однако, правильный путь не всегда доступен. Буквально только что моим героическим друзьям-1с-никам потребовалось налету узнавать статус оператора. Они у меня прикормленные, к лотку приученные, и вообще няшки, так что я уверен, что запросами они мне систему не завалят. Поэтому родился следующий бред: получаем от них через php-скрипт GET-запрос, вызываем астер с нужными параметрами, отдаем результат, а они пусть обрабатывают.

У меня стоит FreePBX, так что апач и астер уже работают под одним пользователем, а exec() в php разрешен. Пишем скрипт, достойный просто пера Шекспира:

<?php
$num=$_GET['num'];
$a="asterisk -x 'core show hint " . $num . "' | grep State | cut -f4 -d':' | cut -f1 -d' '";
echo exec($a);
?>

1с обращается GET-запросом вида

http://10.10.10.10/devstate.php?num=106

и получает в ответ Unavailable, Ringing, InUse или Idle, в зависимости от текущего состояния устройства.


Вот и все, малята! Но помните, что так безобразничать можно только в том случае, если те, кто будут получать статусы, более-менее адекватные.

#asterisk #onestringscript #freepbx #php
Отправка уведомлений в телеграм с помощью простейшего бота

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

Заметка ценности не представляет, и в первую очередь нужна мне, чтобы в следующий раз в попыхах не вспоминать, как заставить telebot работать с socks

В первую очередь, нужно бота создать, делается это с помощью служебного бота @BotFather, который даст нам token нашего бота. Затем, создадим канал, добавим туда нашего бота по имени в качестве администратора. Внимание! Канал нужно создать публичным. Используя любую машину, где есть доступ к телеграму, получим id нашего канала:

curl https://api.telegram.org/bot<токен>/getChat?chat_id=@<название канала>

В выхлопе будет json, содержащий id. После этого канал можно сделать приватным, id у него уже не изменится.

Поставим все необходимое
apt install python3-pip
pip3 install setuptools
pip3 install pytelegrambotapi
pip3 install requests[socks]

requests[socks] нам будет необходим для того, чтобы наш бот умел работать через socks-прокси. Код поражает своей элементарностью:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import telebot
from telebot import apihelper
try:
id,message=sys.argv[1:]
except:
print('Необходимо 2 аргумента - id и сообщение')
exit(1)


apihelper.proxy={'https':'socks5h://proxyuser@proxypass@domain.ltd:port'}
token = '10300000:AAGRVSSSSSSSSSSSSS'
bot=telebot.TeleBot(token)
bot.send_message(id, message)

На входе принимаем id чата, группы, канала - не принципиально, на выходе имеем сообщение в канал. Понятно, что любой человек, "знакомый" с ботом, может принимать сообщения себе в личку от этого бота, нужно только указать личный id, узнать который можно методом, описанным в начале, или через бота @userinfobot Естественно, это просто маленькая заготовка, и следует расширить функциональность бота до интерактива, о чем я уже писал ранее.


UDP для любителей однострочников на баше:



curl -x socks5h://proxyuser:proxypass@proxydomain.ltd:[proxyport] "https://api.telegram.org/bot103000000:XXXXXXXXXXXXX/sendMessage?chat_id=[id]&text=[sometext] "


#python #telegram #onestringscript #bash