Русский
Русский
English
Статистика
Реклама

Jq

Jsqry лучше, чем jq

30.10.2020 16:06:21 | Автор: admin

В своей прошлой статье на Хабре я писал про библиотеку Jsqry, которая предоставляет простой и удобный язык запросов (DSL) к объектам JSON. С тех пор прошло много времени и библиотека тоже получила свое развитие. Отдельный повод для гордости библиотека имеет 98% покрытие кода тестами. Однако в этой статье речь не совсем о ней.


Думаю, многие из вас знакомы с инструментом jq, который является практически стандартом де-факто для работы с JSON в командной строке и скриптах. Я тоже являлся её активным пользователем. Но меня все время беспокоила неоправданная сложность и неинтуитивность синтаксиса запросов этой утилиты. И не меня одного, вот лишь несколько цитат с hacker news:


I have been using jq for years and still can't get it to work quite how I would expect it to.

I have the same issue with jq. I need to use my google fu to figure out how to do anything more than a simple select.

I don't know what the term would be, mental model, but I just can't get jq to click. Mostly because i only need it every once in a while. It's frustrating for me because it seems quite powerful.

I know I might be a dissenting opinion here, but I can never wrap my head around jq. I can manage jq ., jq .foo and jq -r, but beyond that, the DSL is just opaque to me.

Let's just say it: jq is an amazing tool, but the DSL is just bad.

Yeah, I find jq similar to writing regexes: I always have to look up the syntax, only get it working after some confusion why my patterns aren't matching, then forget it all in a few days so have to relearn it again later.

Одним словом, вы уже наверное догадались. Пришла идея, а почему бы не обратить мою JS библиотеку в исполняемый файл для командной строки. Здесь есть один нюанс. Библиотека написана на JS и её DSL также опирается на JS. Это значит, что надо найти способ упаковать программу и какой-нибудь JS-runtime в самодостаточный исполняемый файл.


jsqry GraalVM edition


Для тех кто еще не в теме (неужели еще есть такие? oO) напомню, что GraalVM это такая прокачанная JVM от Oracle с дополнительными возможностями, самые заметные из которых:


  1. Полиглотная JVM возможность бесшовного совместного запуска Java, Javascript, Python, Ruby, R, и т.д. кода
  2. Поддержка AOT-компиляции компиляция Java прямо в нативный бинарник
  3. Улучшения в JIT-компиляторе Java.

Освежить представление о Graal можно, например, в этой хабра-статье.


Теоретически, объединение возможностей пунктов 1. и 2. должно решить поставленную задачу обратить код на JS в исполняемый файл.


Так родился проект https://github.com/jsqry/jsqry-cli. Правда, не спешите добавлять в закладки в данный момент проект deprecated. Идея оказалась рабочей, но непрактичной. Дело в том, что размер исполняемого файла получался 99 Мб. Как-то не очень хорошо для простой утилиты командной строки. Тем более, если сравнить с jq с её размером 3.7 Мб для последней версии для Linux 64.


В идеале хотелось бы получить размер не больше мегабайта.


Тем не менее, решил оставить этот репозиторий как практический пример того как собрать из Java + JS кода исполняемый файл при помощи GraalVM.


Небольшой обзор этого решения


Решение имеет основной код запускаемого приложения в единственном файле App.java. Этот код выполняет обработку параметров командной строки, используя стандартную java-библиотеку Apache Commons CLI.


Далее java-код вызывает код на javascript из файлов, находящихся в директории ресурсов src/main/resources.


При этом интересный момент. Вроде-бы простейший код для вычитывания содержимого файла из ресурса


scripts.add(new String(Files.readAllBytes(Paths.get(jsFileResource.toURI()))));

под Граалем (то есть, будучи скомпилированным через native-image) падало с


java.nio.file.FileSystemNotFoundException: Provider "resource" not installed

Выручил древний "хак" для чтения строки из InputStream


scripts.add(new Scanner(jsFileResource.openStream()).useDelimiter("\\A").next());

Короче говоря, надеяться на 100% поддержку всех функций стандартной Java Граалем все еще не приходится.


Недавно аналогичной неприятной находкой оказалось отсутствие поддержки java.awt.Graphics. Это помешало использовать GraalVM для реализации AWS Lambda для конвертации картинок.


jsqry QuickJS edition


Где-то в это же время я узнал о новом компактном движке JS QuickJS от гениального французского программиста Фабриса Беллара. В своем составе этот инструмент несёт компилятор qjsc джаваскрипта в исполняемый файл. Также поддерживается почти полная совместимость с ES2020. То что нужно!


Таким образом, появилась вторая инкарнация CLI-версии jsqry: https://github.com/jsqry/jsqry-cli2.
Этот подход оказался более жизнеспособным и уже принес несколько релизов.


Итак, что же такое jsqry?


jsqry это маленькая утилита командной строки (похожая на jq) для выполнения запросов к JSON используя "человеческий" DSL.


Цель этой разработки представить функционал JS библиотеки jsqry в форме интерфейса командной строки.


Примеры использования


запрос


$ echo '[{"name":"John","age":30},         {"name":"Alice","age":25},         {"name":"Bob","age":50}]' | jsqry 'name'[  "John",  "Alice",  "Bob"]

первый элемент


$ echo '[{"name":"John","age":30},         {"name":"Alice","age":25},         {"name":"Bob","age":50}]' | jsqry -1 'name'"John"

использование параметризации запроса


$ echo '[{"name":"John","age":30},{"name":"Alice","age":25},{"name":"Bob","age":50}]' \    | jsqry '[ _.age>=? && _.name.toLowerCase().startsWith(?) ]' --arg 30 --arg-str joh [  {    "name": "John",    "age": 30  }]

использование в роли простого JSON pretty-printer


$ echo '[{"name":"John","age":30},{"name":"Alice","age":25},{"name":"Bob","age":50}]' \ | jsqry[  {    "name": "John",    "age": 30  },  {    "name": "Alice",    "age": 25  },  {    "name": "Bob",    "age": 50  }]

Выходной JSON утилиты по умолчанию отформатирован. И раскрашен!


что-то более хитрое


Отфильтровать элементы больше 2, добавить к каждому 100, отсортировать по убыванию и взять 2 последних элемента. Комбинируя эти возможности вы можете строить сколь угодно сложные запросы. Узнать больше о поддерживаемом DSL.


$ echo '[1,2,3,4,5]' | jsqry '[_>2] {_+100} s(-_) [-2:]'[  104,  103]

полная мощь JS


Поскольку jsqry вмещает полноценный JS-движок в исполняемом файле менее 1 Мб, полная мощь JS в ваших руках!


$ echo '["HTTP://EXAMPLE.COM/123",          "https://www.Google.com/search?q=test",          "https://www.YouTube.com/watch?v=_OBlgSz8sSM"]' \ | jsqry '{ _.match(/:\/\/([^\/]+)\//)[1].toLowerCase() }'[  "example.com",  "www.google.com",  "www.youtube.com"]

help-сообщение


$ jsqryjsqry ver. 0.1.2Usage: echo $JSON | jsqry 'query' -1,--first     return first result element -h,--help      print help and exit -v,--version   print version and exit -c,--compact   compact output (no pretty-print) -u,--unquote   unquote output string(s) -as ARG, --arg-str ARG  supply string query argument -a ARG, --arg ARG      supply query argument of any other type

Небольшое сравнение с jq


А здесь я подготовил небольшое практическое сравнение jq и jsqry на примерах.


Установка


Текущая версия (на момент написания): 0.1.2.


К сожалению, только Linux x64 поддерживается в данный момент. Надеюсь, поддержка других платформ будет скоро добавлена. Буду рад здесь вашей помощи.


Чтобы установить или обновить утилиту, просто выполните в командной строке приведенную ниже команду:


$ sudo bash -e -c "wget https://github.com/jsqry/jsqry-cli2/releases/download/v0.1.2/jsqry-linux-amd64 -O/usr/local/bin/jsqrychmod +x /usr/local/bin/jsqryecho \"jsqry \$(jsqry -v) installed successfully\" "

О тестировании CLI-утилиты


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


Попытав Гугл запросами вида "bash unit testing" и отметя варианты BATS, ShellSpec, Bach и несколько других подходов, как чересчур тяжеловесные для моего случая, а также самописную систему тестирования (картинка про 14 стандартов), остановился на решении tush, гениальном в своей простоте.


Тесты на tush представляют собой текстовый файл в таком синтаксисе


$ command --that --should --execute correctly| expected stdout output$ command --that --will --cause error@ expected stderr output? expected-exit-code

Причем tush разбирает только строки начинающиеся на $, |, @ и ? все остальные могут быть любым текстом, например описанием соответствующих тестов. При запуске теста инструмент запускает все строки, начинающиеся на $ и просто сравнивает реальный вывод с ожидаемым, используя обычный diff. В случае отличия тест заканчивается неудачей, а diff отличия выводится пользователю. Пример:


$ /bin/bash /home/xonix/proj/jsqry-cli2/tests.sh--- tests.tush expected+++ tests.tush actual@@ -1,5 +1,5 @@ $ jsqry -v-| 0.1.2+| 0.1.1 $ jsqry -h | jsqry ver. 0.1.1!!! TESTS FAILED !!!

Таким образом удалось покрыть тестами базовые сценарии работы с утилитой в виде одного файла
tests.tush.


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


Удалось этот тестовый сценарий реализовать в виде GitHub Action, который запускается на каждый коммит, гарантируя корректность каждого изменения и предоставляя замечательный бейдж:


Build and test


Другие особенности решения


Раскрашивание JSON


Добавить раскраску выходного JSON оказалось на удивление просто. Решение основано на подходе из проекта zvakanaka/color-json с немного оптимизированными цветами, которые были подобраны на основе прекраснейшего StackOverflow комментария. Для примера привожу сравнение раскраски с jq. В моей версии строки более яркие, а null имеет красный цвет для пущей заметности.


screenshot


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


Подключение npm-версии библиотеки в QuickJS


Опишу немного процесс по которому npm-версия библиотеки jsqry подтягивается и включается в результирующий исполняемый файл. Для этого присутствует стандартный package.json с необходимой версией библиотеки. Библиотека вытягивается стандартным npm i. Затем используется небольшой скрипт prepare-for-qjs.py, роль которого состоит в замене экспортирования в стиле nodejs на экспортирование в стиле модулей ES, только последнее поддерживается движком QuickJS. Далее уже полученный файл импортируется в основной код утилиты jsqry-cli.js.


Чтение входной строки в UTF-8 в QuickJS


В случае QuickJS некоторой мороки стоит считывание строки из stdin. Дело в том, что минималистичная стандартная библиотека, доступная в QuickJS, реализует только считывание байтов. Поэтому понадобился некоторый ручной код, чтоб перегнать байтики UTF-8 в JS-строку. К счастью, его не пришлось изобретать, а удалось позаимствовать из другого проекта на QuickJS: twardoch/svgop.


Сборка утилиты


Сборка утилиты выполняется скриптом build.sh.


Перечислю несколько "фишек" этого скрипта, которые оказались весьма полезными.


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


Второе скрипт build.sh автоматически скачивает и компилирует заданную версию QuickJS, а скрипт tests.sh выполняет то же для инструмента тестирования tush. Очень удобно можно мгновенно продолжить разработку проекта на другой машине без лишних телодвижений.


Третий момент. В самом конце сборки выполняется команда ls -lh jsqry чтоб показать размер результирующего файла. Как я уже упомянул, я немного параноидален на этот счет, хочется чтоб CLI-утилита имела наименьший размер. Я рад, что это принесло полезный побочный результат помогло устранить регрессию, выявленную этой проверкой в одном из прошлых релизов QuickJS.


В данный момент размер исполняемого файла составляет 652 KB. Мне кажется, довольно неплохо, учитывая что файл включает в себя полноценный движок современного стандарта JS.


В качестве послесловия


Прошу заинтересовавшихся попробовать представленную утилиту как замену jq. Также буду рад услышать ваши пожелания по доработке и конструктивную критику.

Подробнее..
Категории: Javascript , Node.js , *nix , Nodejs , Cli , Json , Jq , Ecmascript , Quickjs , Query

Перевод 5 современных альтернатив старым инструментам командной строки Linux

29.06.2020 14:12:48 | Автор: admin
Используя более современные альтернативы наряду со старыми инструментами командной строки, можно получить больше удовольствия и даже повысить производительность труда.



В повседневной работе в Linux / Unix мы используем множество инструментов командной строки например, du для мониторинга использования диска и системных ресурсов. Некоторые из этих инструментов существуют уже давно. Например, top появился в 1984 году, а первый релиз du датируется 1971 годом.
За прошедшие годы эти инструменты были модернизированы и портированы на разные системы, но в целом далеко не ушли от своих первых версий, их внешний вид и usability также сильно не изменились.

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


1. ncdu vs du


NCurses Disk Usage (ncdu) похож на du, но с интерактивным интерфейсом на основе библиотеки curses. ncdu отображает структуру каталогов, которые занимают большую часть вашего дискового пространства.

ncdu анализирует диск, а затем отображает результаты, отсортированные по наиболее часто используемым каталогам или файлам, например:

ncdu 1.14.2 ~ Use the arrow keys to navigate, press ? for help--- /home/rgerardi ------------------------------------------------------------   96.7 GiB [##########] /libvirt   33.9 GiB [###       ] /.crc    7.0 GiB [          ] /Projects.   4.7 GiB [          ] /Downloads.   3.9 GiB [          ] /.local    2.5 GiB [          ] /.minishift    2.4 GiB [          ] /.vagrant.d.   1.9 GiB [          ] /.config.   1.8 GiB [          ] /.cache    1.7 GiB [          ] /Videos    1.1 GiB [          ] /go  692.6 MiB [          ] /Documents. 591.5 MiB [          ] /tmp  139.2 MiB [          ] /.var  104.4 MiB [          ] /.oh-my-zsh   82.0 MiB [          ] /scripts   55.8 MiB [          ] /.mozilla   54.6 MiB [          ] /.kube   41.8 MiB [          ] /.vim   31.5 MiB [          ] /.ansible   31.3 MiB [          ] /.gem   26.5 MiB [          ] /.VIM_UNDO_FILES   15.3 MiB [          ] /Personal    2.6 MiB [          ]  .ansible_module_generated    1.4 MiB [          ] /backgrounds  944.0 KiB [          ] /Pictures  644.0 KiB [          ]  .zsh_history  536.0 KiB [          ] /.ansible_async Total disk usage: 159.4 GiB  Apparent size: 280.8 GiB  Items: 561540


По записям можно перемещаться с помощью клавиш со стрелками. Если вы нажмёте Enter, ncdu отобразит содержимое выбранного каталога:

--- /home/rgerardi/libvirt ----------------------------------------------------                         /..   91.3 GiB [##########] /images    5.3 GiB [          ] /media


Вы можете использовать этот инструмент, чтобы, например, определить, какие файлы занимают больше всего дискового пространства. В предыдущий каталог можно перейти, нажав клавишу со стрелкой влево. С помощью ncdu вы можете удалить файлы, нажав клавишу d. Перед удалением он запрашивает подтверждение. Если вы хотите отключить функцию удаления, чтобы предотвратить случайную потерю ценных файлов, используйте опцию -r для включения режима доступа только для чтения: ncdu -r.

ncdu доступен для многих платформ и дистрибутивов Linux. Например, вы можете использовать dnf для его установки на Fedora непосредственно из официальных репозиториев:

$ sudo dnf install ncdu


2. htop vs top


Htop это интерактивная утилита для просмотра процессов, похожая на top, но из коробки обеспечивающая приятное взаимодействие с пользователем. По умолчанию htop отображает ту же информацию, что и top, но в более наглядном и красочном виде.

По умолчанию htop выглядит так:



В отличие от top:



Кроме того, в верхней части htop отображает обзорную информацию о системе, а нижней части панель для запуска команд с помощью функциональных клавиш. Вы можете настроить её, нажав F2, чтобы открыть экран настройки. В настройках можно изменить цвета, добавить или удалить метрики или изменить параметры отображения панели обзора.

Хотя, покрутив настройки последних версий top, тоже можно добиться похожего usability, htop предоставляет удобные конфигурации по умолчанию, что делает его более практичным и простым в использовании.

3. tldr vs man


Инструмент командной строки tldr отображает упрощённую справочную информацию о командах, в основном примеры. Его разработало сообщество tldr pages project.

Стоит отметить, что tldr это не замена man. Он по-прежнему является каноническим и наиболее полным инструментом вывода справочных страниц. Однако в некоторых случаях man является избыточным. Когда вам не нужна исчерпывающая информация о какой-либо команде, вы просто пытаетесь запомнить основные варианты её использования. Например, страница man для команды curl содержит почти 3000 строк. Страница tldr для curl имеет длину 40 строк. Её фрагмент выглядит так:

$ tldr curl# curl  Transfers data from or to a server.  Supports most protocols, including HTTP, FTP, and POP3.  More information: <https://curl.haxx.se>.- Download the contents of an URL to a file:  curl http://example.com -o filename- Download a file, saving the output under the filename indicated by the URL:  curl -O http://example.com/filename- Download a file, following [L]ocation redirects, and automatically [C]ontinuing (resuming) a previous file transfer:  curl -O -L -C - http://example.com/filename- Send form-encoded data (POST request of type `application/x-www-form-urlencoded`):  curl -d 'name=bob' http://example.com/form                                                                                            - Send a request with an extra header, using a custom HTTP method:  curl -H 'X-My-Header: 123' -X PUT http://example.com                                                                                  - Send data in JSON format, specifying the appropriate content-type header:  curl -d '{"name":"bob"}' -H 'Content-Type: application/json' http://example.com/users/1234... TRUNCATED OUTPUT


TLDR означает слишком длинно; не читал: то есть, некоторый текст был проигнорирован из-за его чрезмерной многословности. Название подходит для этого инструмента, потому что man-страницы, хотя и полезны, но иногда бывают слишком длинными.

Для Fedora tldr был написан на Python. Вы можете установить его с помощью менеджера dnf. Обычно для работы инструмента необходим доступ к интернету. Но клиент Python в Fedora позволяет загружать и кэшировать эти страницы для автономного доступа.

4. jq vs sed/grep


jq это JSON-процессор для командной строки. Он похож на sed или grep, но специально разработан для работы с данными в формате JSON. Если вы разработчик или системный администратор, который использует JSON в повседневных задачах, этот инструмент для вас.

Основное преимущество jq перед стандартными инструментами обработки текста, такими как grep и sed, заключается в том, что он понимает структуру данных JSON, позволяя создавать сложные запросы в одном выражении.

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

{  "apiVersion": "v1",  "kind": "Pod",  "metadata": {    "labels": {      "app": "myapp"    },    "name": "myapp",    "namespace": "project1"  },  "spec": {    "containers": [      {        "command": [          "sleep",          "3000"        ],        "image": "busybox",        "imagePullPolicy": "IfNotPresent",        "name": "busybox"      },      {        "name": "nginx",        "image": "nginx",        "resources": {},        "imagePullPolicy": "IfNotPresent"      }    ],    "restartPolicy": "Never"  }}


Запустите grep для поиска строки name:

$ grep name k8s-pod.json        "name": "myapp",        "namespace": "project1"                "name": "busybox"                "name": "nginx",


grep вернул все строки, содержащие слово name. Вы можете добавить ещё несколько параметров в grep, чтобы ограничить его, и с помощью некоторых манипуляций с регулярными выражениями найти имена контейнеров.

Чтобы получить этот же результат с помощью jq, достаточно написать:

$ jq '.spec.containers[].name' k8s-pod.json"busybox""nginx"


Эта команда выдаст вам имена обоих контейнеров. Если вы ищете только имя второго контейнера, добавьте индекс элемента массива в выражение:

$ jq '.spec.containers[1].name' k8s-pod.json"nginx"


Поскольку jq знает о структуре данных, он даёт те же результаты, даже если формат файла незначительно изменится. grep и sed в этом случае могут работать некорректно.

У jq много функций, но для их описания нужна ещё одна статья. Для получения дополнительной информации обратитесь к странице проекта jq или к tldr.

5. fd vs find


fd это упрощённая альтернатива утилите find. Fd не призван заменить её полностью: в нём по умолчанию установлены наиболее распространённые настройки, определяющие общий подход к работе с файлами.

Например, при поиске файлов в каталоге репозитория Git, fd автоматически исключает скрытые файлы и подкаталоги, включая каталог .git, а также игнорирует шаблоны из файла .gitignore. В целом, он ускоряет поиск, выдавая более релевантные результаты с первой попытки.

По умолчанию fd выполняет поиск без учёта регистра в текущем каталоге с цветным выводом. Тот же поиск с использованием команды find требует ввода дополнительных параметров в командной строке. Например, чтобы найти все файлы .md (или .MD) в текущем каталоге, нужно написать такую команду find:

$ find . -iname "*.md"


Для fd она выглядит так:

$ fd .md


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

fd доступен для многих дистрибутивов Linux. В Fedora его можно установить так:

$ sudo dnf install fd-find


Необязательно от чего-то отказываться


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



На правах рекламы


Многие наши клиенты уже оценили преимущества эпичных серверов!
Это виртуальные серверы с процессорами AMD EPYC, частота ядра CPU до 3.4 GHz. Максимальная конфигурация позволит оторваться на полную 128 ядер CPU, 512 ГБ RAM, 4000 ГБ NVMe. Спешите заказать!

Подробнее..

Почему работать в консоли настолько приятно? Так задумано отцами-основателями Unix

19.04.2021 12:12:03 | Автор: admin

Кен Томпсон и Деннис Ритчи

Unix. Легендарная операционная система оказала огромное влияние на разработку программного обеспечения и всю информатику в целом. Из неё выросли целые семейства Unix-подобных ОС, которыми все мы пользуемся.

Язык программирования Си, Ричард Столлман и GNU, движение Open Source, Линус Торвальдс с ядром Linux, маки, айфоны и Android. Почти всё в системном программировании 21века можно отследить до истоков до Unix.

Unix это фундаментальная база. Но что же в ней такого особенного? Есть один секрет. Точнее, два.

Философия Unix


Есть две причины, почему Unix имела такой успех, распространившись по всему миру. Во-первых, она написана на высокоуровневом языке Си, что обеспечивало и переносимость возможность установки на любых компьютерах, и адаптирование системы для разнообразных специфических требований. Прежде операционные системы писали на ассемблере конкретного компьютера.

Во-вторых это была правильная операционная система. Сделанная в соответствии с некими общими принципами, в соответствии с цельной философией Unix.

Брайан Керниган и Роб Пайк в книге Unix. Программное окружение формулируют основную идею этой философии:

Эффективность UNIX определяется применением особого подхода к программированию, философией использования компьютера. Для того, чтобы описать эту философию, одного предложения, конечно же, недостаточно, но вот её основная идея мощность системы в огромной степени определяется взаимодействием программ, а не их наличием.

Многие Unix-программы по отдельности выполняют довольно тривиальные задачи, но будучи объединёнными с другими, образуют полный и полезный инструментарий.

Другими словами, философия Unix это взаимодействие программ. Как говорил в своей презентации Брайан Керниган, программы Unix словно строительные блоки, которые можно комбинировать, складывая в эффективные конструкции. Выход одной программы является входом другой программы. Своеобразный конвейер (пайп).

Команды сочетаются в конвейер не только стандартными, очевидными способами. Бывают и весьма нетривиальные сочетания.

Волшебные конвейеры


Проще всего понять эту магию на конкретных примерах. пусть этот будет хит-парад авторов из репозитория по количеству коммитов, загрузка мемов с Reddit и смена обоев для рабочего стола каждый час согласно оценкам в подреддите /r/earthporn.

Список лидеров по числу коммитов


Начнём с простого примера: отобразить список авторов репозитория git, отсортированных по количеству коммитов. Если представить задачу в терминах конвейеров, то она довольно простая. Выводим логи коммитов командой git log. Опция --format=<format> позволяет указать, в каком формате отображать коммиты. В нашем случае --format='%an' выводит только имена авторов для каждого коммита.

$ git log --format='%an'AliceBobDeniseDeniseCandiceDeniseAliceAliceAlice

Теперь утилита sort сортирует их по алфавиту.

$ git log --format='%an' | sortAliceAliceAliceAliceBobCandiceDeniseDeniseDenise

Далее используем uniq.

$ git log --format='%an' | sort | uniq -c    4 Alice    1 Bob    1 Candice    3 Denise

Согласно man-странице uniq, она учитывает только соседние совпадающие строки. Вот почему нужно было сначала отсортировать список. Флаг -c выводит перед каждой строкой количество вхождений.

Как видим, выдача по-прежнему отсортирована по алфавиту. Осталось только изменить способ сортировки по числовым значениям. Для этого есть флаг -n.

$ git log --format='%an' | sort | uniq -c | sort -nr    4 Alice    3 Denise    1 Candice    1 Bob

Флаг -r указывает на обратный порядок сортировки. Вот и всё. Теперь у нас есть список авторов, отсортированных по количеству коммитов.

Просмотр мемов из /r/memes и установка обоев из /r/earthporn


Вы знали, что можно добавить .json к любому URL на Reddit, чтобы получить выдачу в формате JSON вместо обычного HTML? Это открывает целый мир возможностей! Например, просмотр мемов прямо из командной строки (ну, не совсем, потому что фактическое изображение будет отображаться в графической программе). Мы можем просто запросить файл напрямую через curl или wget: https://reddit.com/r/memes.json.

$ wget -O - -q 'https://reddit.com/r/memes.json''{"kind": "Listing", "data": {"modhash": "xyloiccqgm649f320569f4efb427cdcbd89e68aeceeda8fe1a", "dist": 27, "children":[{"kind": "t3", "data": {"approved_at_utc": null, "subreddit": "memes","selftext": "More info available at....'......

Wget принимает опцию -O с указанием файла для записи. Большинство программ, которые принимают такую опцию, также допускают значение -, что означает стандартный вывод stdout (или ввод, в зависимости от контекста). Опция -q просто означает работу в тихом режиме, не отображая информацию типа статуса скачивания. Теперь у нас есть большая структура JSON. Чтобы проанализировать и осмысленно использовать эти данные в командной строке, можно взять утилиту jq, аналог sed/awk для JSON. У неё простой интуитивно понятный язык.

Ответ JSON выглядит примерно так:

{    "kind": "Listing",    "data": {        "modhash": "awe40m26lde06517c260e2071117e208f8c9b5b29e1da12bf7",        "dist": 27,        "children": [],        "after": "t3_gi892x",        "before": null    }}

Итак, здесь у нас тип Listing и массив children. Каждый элемент этого массива отдельный пост.

Вот как выглядит один из элементов массива:

{    "kind": "t3",    "data": {        "subreddit": "memes",        "selftext": "",        "created": 1589309289,        "author_fullname": "t2_4amm4a5w",        "gilded": 0,        "title": "Its hard to argue with his assessment",        "subreddit_name_prefixed": "r/memes",        "downs": 0,        "hide_score": false,        "name": "t3_gi8wkj",        "quarantine": false,        "permalink": "/r/memes/comments/gi8wkj/its_hard_to_argue_with_his_assessment/",        "url": "https://i.redd.it/6vi05eobdby41.jpg",        "upvote_ratio": 0.93,        "subreddit_type": "public",        "ups": 11367,        "total_awards_received": 0,        "score": 11367,        "author_premium": false,        "thumbnail": "https://b.thumbs.redditmedia.com/QZt8_SBJDdKLVnXK8P4Wr_02ALEhGoGFEeNhpsyIfvw.jpg",        "gildings": {},        "post_hint": "image",        ".................."        "много строк скипнуто"        ".................."    }}

Здесь много интересных атрибутов, в том числе URL картинки с мемом.

Мы можем легко получить список всех URL со всех постов:

$ wget -O - -q reddit.com/r/memes.json | jq '.data.children[] |.data.url'"https://www.reddit.com/r/memes/comments/g9w9bv/join_the_unofficial_redditmc_minecraft_server_at/""https://www.reddit.com/r/memes/comments/ggsomm/10_million_subscriber_event/""https://i.imgur.com/KpwIuSO.png""https://i.redd.it/ey1f7ksrtay41.jpg""https://i.redd.it/is3cckgbeby41.png""https://i.redd.it/4pfwbtqsaby41.jpg"......

Игнорируйте первые две ссылки, это в основном закреплённые посты от модераторов.

Утилита jq считывает данные из стандартного входа и получает JSON, который мы видели ранее. Затем указан массив постов .data.children. Синтаксис .data.children[] | .data.url означает: пройти по каждому элементу массива и вывести поле url, которое находится в поле data каждого элемента.

Таким образом, мы получаем список URL всех топовых мемов в подреддите /r/memes на данный момент. Если хотите посмотреть лучшие посты недели, нужно писать https://reddit.com/r/memes/top.json?t=week. Топ всех времён: t=all, за год: t=year и так далее.

Как только у нас есть список всех URL, можно просто передать его в xargs. Это действительно полезная утилита для построения командных строк из стандартного ввода. Из описания:

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

Пустые строки игнорируются.

То есть такая команда:

$ echo "https://i.redd.it/4pfwbtqsaby41.jpg" | xargs wget -O meme.jpg -q

будет равнозначна этой:

$ wget -O meme.jpg -q "https://i.redd.it/4pfwbtqsaby41.jpg"

Теперь можно просто передать список URL'ов в просмотрщик изображений feh или eog, который принимает URL в качестве допустимого аргумента.

$ wget -O - -q reddit.com/r/memes.json | jq '.data.children[] |.data.url' | xargs feh

И у нас запускается feh с мемами, которые можно листать клавишами со стрелками, словно это картинки на локальном диске.



Или можно загрузить все изображения с помощью wget, заменив feh на wget в строке выше.

А возможности безграничны. Ещё один вариант использования картинок с Reddit через JSON установка топовой картинки подреддита /r/earthporn в качестве обоев рабочего стола:

$ wget -O - -q reddit.com/r/earthporn.json | jq '.data.children[] |.data.url' | head -1 | xargs feh --bg-fill

Если хотите, можно настроить cron-задание, которое выполняется каждый час.


Лес в Нидерландах [20001333]


Гренландия [40323024]

Конечно, вместо /r/earthporn можно брать картинки из других подреддитов.

Вот в чём мощь конвейеров Unix. Одна-единственная строка делает всё: скачивает файл JSON, разбирает его, находит нужные данные, потом скачивает картинку по URL и устанавливает её в качестве обоев.

Это всего несколько случайных примеров. В реальности можно очень многое сделать однострочной командой в консоли, построив конвейер из простых утилит.

Работа, которая доставляет удовольствие


Особая философия Unix настолько глубока и фундаментальна, что породила целые классы Unix-подобных систем, к числу которых относятся BSD, macOS и Linux. Все они построены на этой философии. А побочный эффект работы в такой системе чувство правильности и цельности. Что так всё и должно работать: из кирпичиков, маленьких строительных блоков, которые сцепливаются в конвейеры любой сложности. Это же гениально.

Интересные факты об отцах-основателях


Может, через много лет Томпсона и Ритчи канонизируют, причислив к лику отцов-основателей разумного компьютерного мира. А сейчас цифровые археологи продолжают откапывать всё новые факты из истории Unix.

Например, в 2014 году исследователь Лея Нойкирхер нашла в дампах исходного дерева BSD 3 файл /etc/passwd с паролями всех ветеранов, таких как Деннис Ричи, Кен Томпсон, Брайан В. Керниган, Стив Борн и Билл Джой.

Для хэшей использовался алгоритм crypt(3) с максимальной длиной пароля 8 символов. Лея взломала их стандартными брутерами john и hashcat. Большинство паролей были очень слабыми. Только пароль Кена Томпсона не поддавался взлому. Даже полный перебор всех строчных букв и цифр (несколько дней) не дал результата. Неужели он использовал специальные символы? Лишь в 2017 году Найджел Уильямс в списке рассылки The Unix Heritage Society раскрыл эту тайну. Пароль со всеми возможными символами оказался q2-q4!: это первый ход пешкой на две клетки в описательной нотации и начало многих типичных дебютов, что очень хорошо вписывается в бэкграунд Кена Томпсона по компьютерным шахматам. Брутфорс на видеокарте AMD Radeon Vega64 занял более четырёх дней.

Некоторые из разработчиков Unix живы и здравствуют. Если хотите посмотреть, какие операционные системы и программы они используют на своих домашних компьютерах вот галерея 2002 года и 2015 года. Каждого в электронном письме попросили сделать скриншот текущего десктопа сразу, как только они прочитают эти слова.


Десктоп Брайана Кернигана (октябрь 2015)

Деннис Ритчи (19412011) в 2002 году использовал необычную установку: его домашний клиент на NT4 подключён по ISDN к удалённому серверу Plan9 в центральном офисе Bell Labs.



Plan9 инновационная ОС, основанная на концепции распределённых вычислений. Любая машина может использовать любые ресурсы с любой другой машины как собственные. Сейчас эту концепцию пытаются реализовать в виде контейнеров, VM и микросервисов, а там она реализована на уровне ядра ОС.

Дальше у нас Брам Моленар, автор многофункционального текстового редактора Vim:


Десктоп Брама Моленара (сентябрь 2002)


Десктоп Брама Моленара (ноябрь 2015)

Джордан Хаббард, один из сооснователей проекта FreeBSD:


Десктоп Джордана Хаббарда (ноябрь 2015)

P. S. К сожалению, Линус Торвальдс не смог сделать скриншот из своей консоли в текстовом режиме.

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



На правах рекламы


Устанавливайте любые операционные системы на наших VDS с мгновенной активацией. Сервер готов к работе через минуту после оплаты!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru