Пингвитон
151 subscribers
4 photos
12 links
иногда пишу тут какие-то полезные штуки про Linux и Python
Download Telegram
Channel created
Не хочется сортировать руками содержимое requirements.txt? Открываете его в vim. Нажимаете shift v -- это включает режим выделения. Нажимаете j до тех пор, пока не выделится всё содержимое файла. Нажмите !, введите sort, нажмите enter. Ву-ху! Строчки зависимостей отсортированы в алфавитном порядке. Чтобы выйти и сохранить файл введите :wq (w -- записать, q -- выйти), нажмите enter.
#vim #sort
Если вы вдруг такие же оригиналы, как я, отказываетесь пользоваться программами, предоставляющими графический интерфейс поверх вашей MongoDB, и пользуетесь консольными утилитами, то пост для вас. Как сделать красивый вывод с данными из mongo? Чтобы это была не сплошная портянка, сложная для чтения и поиска нужного куска, а симпатичный human-readable, json-like вывод?

Вам нужен файл ~/.mongorc.js (обратите внимание, что он должен лежать в вашей домашней директории), в нем всего одна строка:

DBQuery.prototype._prettyShell = true

Наслаждайтесь pretty print'ом с отступами.

#mongo #mongodb #prettyprint
Есть прекрасный инструмент для написания тестов -- pytest (вы же, конечно, покрываете тестами свой код?). В pytest есть фикстура tmpdir, которая позволит вам не страдать над тестами, в которых необходимо проверять работу файловой системы. Например, мне нужно было проверить, что корректно работает функция, очищающая директорию от старых файлов.

def test_clear_cache(tmpdir):
pass```Фикстура tmpdir указывается в качестве параметра вашему тесту.

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

```kcarectl.PATCH_CACHE = str(tmpdir)```-- ничего не надо придумывать, указывать какие-то точные пути и пр., tmpdir сам со всем разберется.

Далее мне нужно создать файлы:

```tmpdir.mkdir("dir").mkdir("level").join("kpatch.bin").ensure(file=True)```Фикстура `tmdir` предоставляет интерфейс, похожий на os.path. Важно: `join` не создает файл, он лишь возвращает объект, с которым можно что-то делать (писать внутрь что-то с помощью `write`, например). Чтобы именно создать файл в вашей файловой системе, нужно использовать `ensure`.

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

```kdir = tmpdir.mkdir("dir").mkdir("level")
kdir.join("kpatch.bin").ensure(file=True).setmtime(i * 3 + 0)
khashdir.join("kpatch.extra.bin").ensure(file=True).setmtime(i * 3 + 1)
Если в тестах вам нужно учитывать время модификации файла, то во время создания вам нужно изменить его самостоятельно (потому что подряд созданные файлы создадутся мгновенно, и их mtime будет одинаков), это можно сделать с помощью метода setmtime. Помните, что это тесты, вам не нужно реальное время, так что для простоты можно использовать 0, 1, 2, 3 и пр. секунды в качестве переданного таймстемпа.

В tmpdir, который является оберткой над py.path, еще много полезных штук, посмотрите документацию обоих:

https://docs.pytest.org/en/latest/tmpdir.html
https://py.readthedocs.io/en/latest/path.html

#pytest #unittests #unittest #test #tests #python #tmpdir
Забыла упомянуть суперполезную и важную фичу tmpdir. Чего ради всё это (:

tmpdir будет создавать ваши тестовые файлы в /tmp/. Он создаст директорию ваших тестов -- pytest-of-<NAME>, а внутри него директории, посвященные конкретному запуску тестов. Он так же будет убирать их за собой: после каждого запуска тестов в pytest-of-<NAME> будет не больше 4-х директорий с запусками, остальные буду удаляться:

~$ ls /tmp/pytest-of-lauvenhelz/
pytest-52 pytest-53 pytest-54 pytest-55 pytest-lauvenhelz```Но что это за pytest-lauvenhelz на последнем месте? Это киллерфича (: tmpdir создает симлинк на директорию с последним запуском тестов:

```~$ ls -la /tmp/pytest-of-lauvenhelz/pytest-lauvenhelz
lrwxrwxrwx 1 lauvenhelz lauvenhelz 53 Feb 27 18:23 /tmp/pytest-of-lauvenhelz/pytest-lauvenhelz -> /tmp/pytest-of-lauvenhelz/pytest-55/test_clear_cache0

То есть вам не нужно каждый раз править путь в ls -la во время разработки тестов, чтобы смотреть, что там создалось-удалилось-изменилось. Вы один раз пишете ls -la /tmp/pytest-of-<NAME>/pytest-<NAME>/ и всё оставшееся время пользуетесь этой командой: tmpdir позаботится, чтобы вы видели свежие результаты.

Наслаждайтесь (:

#pytest #unittests #unittest #test #tests #python #tmpdir
Иногда пишешь очень длинную команду в консоли и где-то в середине или почти в самом конце понимаешь, что нужно сначала запустить другую команду. И обязательно в той же директории, где сейчас находишься. Что делать? ctrl+c грохнет всю запись, её потом придется вводить заново. Копировать? Мучительно, если команда длинная и с переносами. Можно открыть другое окно терминала, донавигироваться до нужной директории, выполнить нужное, а потом вернуться в окно с недописанной команду и дописать -- тоже долго и мучительно.

Можно быстро закомментировать с помощью #.

ctrl+a быстро переместит ваш курсор в начало команды. Ставите #, нажимаете энтер. Команда сохранилась в истории, но ничего не сделала -- вы ввели комментарий. Выполняете нужные действия, потом ищете в истории недописанную команду, удаляете знак #, дописываете, запускаете.

~/dev/$ #mv scripts/kcaretest/deploy/kcarectl_tests/
Немеренное количество баша написано людьми для того, чтобы отсортировать вывод какой-то утилиты по конкретной колонке. Хотя его можно было не писать, а использовать sort.

Обычно sort используют без параметров. Максимум -- используют -n. Он говорит sort'у о том, что сортируемое надо интерпетировать в качестве чисел. Например, без -n:

~/dev$ echo -e "11\n112\n23\n3" | sort
11
112
23
3

А вот с -n:

~/dev$ echo -e "11\n112\n23\n3" | sort -n
3
11
23
112

Но sort умеет сортировать и по колонкам. Возьмём утилиту lsmod. Неважно, что она делает, главное -- она выводит 4 колонки. 1 -- название, 2 -- размер. И мы хотим отсортировать вывод по размеру. Вот тут люди пишут много баша, а можно ограниться одной строкой:

lsmod | sort -n -k2,2

Запуск утилиты lsmod, пайп (`|`), который переводит её вывод в stdin следующего sort.

Про параметры sort'а. В -k указан диапазон колонок, по которым надо сортировать: от 2 до 2 (нумерация колонок от 1). Вы так же можете указывать дополнительные параметры сортировки в конкретный -k:

lsmod | sort -k2,2n

И если вы хотите сортировать по нескольким колонкам, которые стоят не рядом или сначала по второй, а потом по первой, то можно указать несколько -k:

lsmod | sort -k2,2n -k1,1r

Эта команда отсортирует вывод lsmod'а по второй колонке (размер) в возрастающем порядке, интерпретируя её в качестве чисел (ключ `-n`), и по первой колонке (имя) в убывающем алфавитном порядке (ключ `-r`).
Точно знаете, что файл (или директория) где-то есть, но не знаете, где именно, и хотите найти? Используйте * вместо тех кусков, которые не знаете, например:

release/*/ff3f1718e8dbed02630e81de240a06277949c43a/221

А чтобы получить полный путь используйте realpath:

$ realpath release/*/ff3f1718e8dbed02630e81de240a06277949c43a/221
/usr/share/kcare-eportal/patches/release/17112017_1/ff3f1718e8dbed02630e81de240a06277949c43a/221

С помощью * еще удобно выводить информацию для нескольких файлов за раз, например:

$ md5sum release/*/ff3f1718e8dbed02630e81de240a06277949c43a/223/fixup_kcare.ko
613287ca699c69ed2190411c27b020cc release/28122017_1/ff3f1718e8dbed02630e81de240a06277949c43a/223/fixup_kcare.ko
613287ca699c69ed2190411c27b020cc release/29032018_1/ff3f1718e8dbed02630e81de240a06277949c43a/223/fixup_kcare.ko

Тут я взяла хеш для двух файлов в разных директориях. В выводе команды: хеш и указание, к какому файлу он принадлежит.
Channel name was changed to «Заметки о Python и Arch Linux»
Channel photo updated
Есть файл с гигантским json'ом, который нужно просмотреть глазами? Но смотреть его одной строкой без форматирования больно и неудобно. Поможет Python:

cat patches/patches.json | python3 -m json.tool

На выходе в консоли будет красивый отформатированный json с отступами, который легко читать и искать нужное.
Чтобы открыть какой-то файл и в реальном времени видеть, что в него пишут, можно использовать tail с опцией -f:

$ tail -f /var/log/nginx/access.log

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

Можно использовать grep. Но если использовать просто grep вот так:

$ tail -f /var/log/nginx/access.log | grep public.list

-- то вы свой запрос не увидите, даже если отправите. grep буферизует результаты и будет ждать, когда появятся ещё какие-то строки, которые можно вывести. Чтобы grep выплевывал каждую новую одинокую появляющуюся строку, используйте опцию --line-buffered:

$ tail -f /var/log/nginx/access.log | grep public.list --line-buffered

Помните, что если используете цепочку грепов, то эту опцию нужно проставить каждому:

$ tail -f /var/log/nginx/access.log | grep public.list --line-buffered | grep username --line-buffered
Ещё я недавно насмотрелась на то, как работают с linux другие и хочу спросить: вы же знаете про команду ctrl-r?

Все команды, которые вы выполняете в терминале, сохраняются. Чтобы посмотреть историю, введите history.

Как быстро навигироваться по истории?

Варианты, как найти команду в терминале, которую вы вводили ранее:
1) если вы вводили ее только что или пару команд назад, то можно просто нажимать клавишу стрелки вверх -- вам последовательно будут показываться команды, которые запускались, от самой свежей к более старым,
2) history | grep <команда> , выделить нужную команду, вставить, запустить -- это как раз тот способ, на который я насмотрелась и который сподвиг меня написать этот пост (не надо так),
3) ctrl-r -- нажимаете сочетание этой клавиши и начинаете вводить команду, которая вам нужна, например ssh, вам покажут самую свежую команду, которая содержит эти символы. Если это не та команда (вы хотите подключиться к другой машине, к которой обращались раньше), то просто нажимаете ctrl-r ещё раз и ещё раз, пока не найдете нужное. Если нажать стрелку вправо, то команда вставится в терминал, но не выполнится (вы можете её редактивровать), если энтер -- команда сразу выполнится.

Пользуйтесь ctrl-r, это удобно!
У вас есть сервер. А на сервере какой-то дикий треш с симлинками. Все друг на друга ссылаются. Симлинк на симлинк на симлинк. Как понять, что вот эта директория -- это то же самое, что вот эта директория? Могу ли я быть уверена, что вот тут: /usr/share/kcare-eportal/patches/test/release лежит то же самое, что и вот тут: /var/www/html/test/release?

Простой и быстрый способ:

[igrechikhina@patches ~]$ ls -d -i /usr/share/kcare-eportal/patches/test/release
1966244 /usr/share/kcare-eportal/patches/test/release
[igrechikhina@patches ~]$ ls -d -i /var/www/html/test/release
1966244 /var/www/html/test/release

-d, чтобы не показывать содержимое директории, а только её саму.
-i, чтобы показать волшебное число для директории.

Если числа, выплюнутые -i, совпали для двух директорий, значит, это одна и та же директория (и вам нужно разбираться, кто кому симлинк).
Продолжая тему "ты ли это" или как сравнить две сущности и убедиться, что это одно и то же. Иногда надо сравнить два файла на одной машине, иногда надо убедиться, что файл у себя на машине и где-то на удалённом сервере -- это один и тот же файл. Так вот -- cksum в помощь.

Вот хочу узнать, одна ли и та же версия файла у меня в репе и сейчас на сервере:

На удалённом:
[root@patches2 ~]# cksum /usr/local/bin/kcare-deploy-prod
1081165413 480 /usr/local/bin/kcare-deploy-prod

На своём:
~$ cksum /home/lauvenhelz/dev/cldlnx/kernelcare/dist-server-scripts/kcare-deploy-prod
3998718679 616 /home/lauvenhelz/dev/cldlnx/kernelcare/dist-server-scripts/kcare-deploy-prod

Вижу, что нет, разные. Первое число -- чексумма, второе число -- размер, оба отличаются.

Ещё есть md5sum, раньше пользовалась ею, но у неё длиннее выводимая чексумма, что не очень удобно, и нет информации о размере файла:

[root@patches2 ~]# md5sum /usr/local/bin/kcare-deploy-prod
a490ae81807608ee2eafe35932cade41 /usr/local/bin/kcare-deploy-prod
Хочу отдельно обратить ваше внимание, что это команды именно для быстрой проверки для себя. Быстро убедиться, что файлы одинаковые или отличаются. Не используйте их в серьёзных задачах -- это ненадёжно (в cksum коллизии возникают легко, в md5sum не так легко, но тоже возникают). Если вам нужна серьёзная проверка и контроль файлов в рамках реализуемой задачи, используйте, например sha256sum.
Когда вы запускаете какую-то команду в консоли, вы, очевидно, запускаете какой-то файл. Как узнать какой и где он лежит? Есть команда which. Во-первых, удобно использовать, чтобы узнать, "кого запускаем-то". Например, когда вы впервые залезли на сервер и разбираетесь, как работают все эти самописные скрипты. Вы не можете сделать cat <команда>, вам нужен путь до файла.

Можно посмотреть путь и потом использовать его в cat:

[root@patches2 ~]# which kcare-deploy-prod
/usr/local/bin/kcare-deploy-prod

А можно сделать всё в одну строчку:

[root@patches2 ~]# cat `which kcare-deploy-prod`
#!/bin/bash
<...тут содержимое файла...>

Во-вторых, конструкцию <команда> `which <другая команда>` можно использовать во всех остальных случаях (: Например, для предыдущего примера с cksum:

[root@patches2 ~]# cksum `which kcare-deploy-prod`
3998718679 616 /usr/local/bin/kcare-deploy-prod
Мне нужно скачать с одного сервера на другой 27 гигабайт. На первый сервер я захожу по ssh и там надо запустить rsync, чтобы вытащить файлы со второго. Сеть отвратительная, будет качаться всю ночь. ssh иногда отваливается. Как быть уверенной, что процесс не помрёт в середине ночи от broken pipe'а, когда ssh отвалится? Ну, и лаптоп не хочется всю ночь включённым держать.

Используете screen. Запускаете, он эмулирует терминал. Выполняете там необходимое (я запускаю rsync, например). И покидаете эмуляцию с помощью ctrl+a, затем d. Эта команда не окончит сессию, а просто позволит вам выйти, "отцепиться":

[root@192-168-246-68 ~]# screen
[detached from 12233.pts-0.192-168-246-68]

Теперь эта сессия будет живой до тех пор, пока вы не закроете её самостоятельно. Запущенная в ней команда в безопасности, не будет прервана и успешно отработает.
Чтобы зайти обратно, используйте screen -r.

Можно создать несколько терминалов. Каждый раз запуская screen, создается новая сессия. Когда захотите вернуться в конкретную сессию, нужно будет ввести её pid. Вот я ввожу screen -r, когда у меня есть несколько эмуляций и вижу:

[root@192-168-246-68 ~]# screen -r
There are several suitable screens on:
16373.pts-0.192-168-246-68 (Detached)
12233.pts-0.192-168-246-68 (Detached)
Type "screen [-d] -r [pid.]tty.host" to resume one of them.

Вводите нужный pid, например, screen -r 12233.pts-0.192-168-246-68 заходите.

Чтобы убить ненужную больше эмуляцию, заходите внутрь и нажимаете ctrl+d, на выходе вам сообщат об окончании сессии:

[root@192-168-246-68 ~]# screen -r 16373.pts-0.192-168-246-68
[screen is terminating]

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