JC, Mengubah Output Tool Command-Line Populer Menjadi JSON
(github.com/kellyjonbrazil)- JC adalah tool yang membantu mempermudah parsing dalam skrip dengan mengubah output dari berbagai tool CLI, format file, dan string umum menjadi JSON
- Menerima input pipe dan mengeluarkan JSON ke
STDOUT, serta mendukung magic syntax yang ditempatkan di depan perintah sepertijc dig example.com - Output default memakai skema ketat per parser, mengonversi angka,
null, boolean, dan field semantik tambahan; JSON mentah sebelum prapemrosesan dapat diakses dengan-ratauraw=True - Juga bisa digunakan sebagai library Python, sehingga hasil dapat diterima dalam bentuk dictionary Python, list dictionary, atau lazy iterable alih-alih JSON
- Untuk pipeline berukuran besar dan berjalan lama, menyediakan streaming parser yang mengeluarkan JSON Lines/NDJSON,
--slurp,--meta-out, plugin parser lokal, serta opsi untuk menekan peringatan kompatibilitas platform
Apa yang Dilakukan JC
- JC(JSON Convert) mengubah output dari berbagai tool CLI, format file, dan string umum menjadi JSON
- Output yang sudah dikonversi dapat diproses lebih lanjut dengan dipipe ke tool seperti
jqataujello - Contohnya,
dig example.com | jc --digmengubah outputdigmenjadi array JSON, lalujq -r '.[].answer[].data'mengekstrak hanya alamat IP - Pekerjaan yang sama juga bisa dijalankan dengan magic syntax seperti
jc dig example.com | jq -r '.[].answer[].data'
Cara Penggunaan CLI dan Library Python
- Penggunaan CLI dasar berbentuk menerima input pipe lalu mencetak representasi JSON
COMMAND | jc [SLICE] [OPTIONS] PARSERcat FILE | jc [SLICE] [OPTIONS] PARSERecho STRING | jc [SLICE] [OPTIONS] PARSER
- magic syntax menambahkan
jcdi depan perintah atau file/procdengan formatjc [SLICE] [OPTIONS] COMMANDataujc [SLICE] [OPTIONS] /proc/<path-to-procfile>- Alias perintah dan shell builtin tidak didukung
- Di Python, dipanggil seperti
jc.parse('dig', cmd_output)- Nilai kembalian bukan string JSON, melainkan bisa berupa dictionary Python, list dictionary, atau lazy iterable dari streaming parser
- Dokumentasi paket Python dapat dilihat melalui
help('jc'),help('jc.lib'), atau dokumentasi online
Representasi Output dan Skema
- Representasi default memakai skema ketat per parser
- Angka yang dikenali dikonversi menjadi nilai JSON
intataufloat - Nilai
Noneyang dikenali dikonversi menjadi JSONnull - Nilai boolean yang dikenali juga dikonversi
- Beberapa parser menambahkan field semantik tambahan
- Angka yang dikenali dikonversi menjadi nilai JSON
- JSON mentah hasil prapemrosesan dapat diakses dengan opsi CLI
-ratauparse(..., raw=True)pada library Python - Skema tiap parser dapat dilihat dari tautan dokumentasi di samping daftar parser
- Output JSON secara default berbentuk compact, dan format pretty dapat digunakan dengan opsi
-p - Output YAML juga tersedia dengan opsi
-yatau--yaml-out
Parser yang Didukung dan Contoh Penggunaan
- Target yang didukung terdiri dari perintah CLI, format file, dan parser string
- Daftar parser di README mencakup
dig,ls,ping,ps,netstat,ifconfig,csv,xml,yaml,/etc/hosts,/etc/passwd,/proc/,systemctl,git log,jwt,url,semver, file terkaitx509, dan lainnya - Contoh output menunjukkan cara mengubah berbagai input menjadi struktur JSON
- Output
arpdikonversi menjadi field alamat, tipe hardware, alamat MAC, dan interface - File CSV dikonversi menjadi array objek dengan header sebagai key
/etc/hostsdikonversi menjadi array IP dan hostnameifconfigdikonversi menjadi objek yang memuat nama interface, MTU, alamat IPv4/IPv6, counter paket dan byte, dan lainnyapingdikonversi menjadi objek yang memuat jumlah paket yang dikirim/diterima, tingkat kehilangan, round-trip time, dan daftar respons
- Output
- Di Ansible, dapat digunakan sebagai filter plugin dari koleksi
community.general
Cara Instalasi
jcdapat diinstal dengan beberapa carapip3 install jc- Repositori paket OS
- Binary per arsitektur dari GitHub Releases
- Contoh instalasi paket OS mencakup berikut ini
- Debian/Ubuntu:
apt-get install jc - Fedora:
dnf install jc - openSUSE:
zypper install jc - Arch:
pacman -S jc - macOS:
brew install jc - FreeBSD: instalasi melalui ports
- Ansible filter plugin:
ansible-galaxy collection install community.general - FortiSOAR connector: instal dari FortiSOAR Connector Marketplace
- Debian/Ubuntu:
Opsi Utama
-a/--about: mencetak informasijcdan parser sebagai JSON atau YAML-d/--debug: mencetak pesan trace saat ada masalah parsing, sementara-ddmenyediakan debugging yang lebih detail-h/--help: mencetak bantuan, dan dokumentasi parser dapat dilihat denganjc -h --parser_name-M/--meta-out: menambahkan metadata seperti timestamp, nama parser, magic command, dan exit code magic command ke output-q/--quiet: menekan pesan peringatan parser, sementara-qqmengabaikan error streaming parser-s/--slurp: membungkus input multi-baris menjadi array-u/--unbuffer: menonaktifkan buffering output-B/--bash-comp,-Z/--zsh-comp: membuat completion script untuk Bash atau Zsh
Slice dan Slurp
- Slice memproses hanya sebagian baris input dengan sintaks
START:STOPyang mirip Python slicing - Misalnya, pada tabel dengan header dan footer, hanya data di tengah dapat dikonversi menjadi JSON dengan
jc 1:-1 --asciitableataujc 1:4 --asciitable - Slice positif dan slice kosong paling efisien dari sisi memori, sedangkan slice negatif memakai lebih banyak memori
- Slurp adalah fitur untuk mengeluarkan beberapa item sekaligus sebagai array pada parser string yang menerima input satu baris
- Contoh: memproses file berisi beberapa alamat IP, satu per baris, dengan
jc --slurp --ip-address
- Contoh: memproses file berisi beberapa alamat IP, satu per baris, dengan
- magic syntax
/procotomatis mendukung slurp saat beberapa file dipilih- Saat mengonversi beberapa file
/proc, field_fileditambahkan agar dapat diketahui setiap objek hasil berasal dari file mana
- Saat mengonversi beberapa file
- Jika
--meta-outdigunakan bersama slurp, output dibungkus dalam struktur yang berisi arrayresultdan objek_jc_meta
Exit Code dan Metadata
- Error fatal internal
jcmenghasilkan exit code100, dan selain itu mengembalikan0 - Saat menggunakan magic syntax,
jcmenyimpan exit code program yang menjadi target parsing dan menambahkannya ke exit codejc- Jika
ifconfigbernilai1danjcbernilai0, exit code gabungannya adalah1 - Jika
ifconfigbernilai0danjcbernilai100, exit code gabungannya adalah100 - Jika keduanya error, exit code gabungannya adalah
101
- Jika
- Saat menggunakan
--meta-outatau-Mpada magic syntax, objek_jc_metamemuat informasi magic command dan exit code
Warna dan Variabel Lingkungan
- Variabel lingkungan
JC_COLORSdapat digunakan untuk menentukan warna key name, keyword, number, dan string- Formatnya adalah
JC_COLORS=<keyname_color>,<keyword_color>,<number_color>,<string_color> - Nilai warna adalah salah satu dari
black,red,green,yellow,blue,magenta,cyan,gray,brightblack,brightred,brightgreen,brightyellow,brightblue,brightmagenta,brightcyan,white,default
- Formatnya adalah
- Jika variabel lingkungan
NO_COLORdisetel, output berwarna dinonaktifkan - Opsi
-Cmemaksa output berwarna dengan prioritas lebih tinggi daripada variabel lingkunganNO_COLORdan opsi-m
Streaming Parser
- Sebagian besar parser membaca seluruh
STDINke memori, melakukan parsing, lalu menserialisasikan dokumen JSON sebagai output - Beberapa streaming parser memproses input baris demi baris begitu diterima dan mengeluarkannya sebagai JSON Lines atau NDJSON
- Contoh:
ls-s,ping-s - Dapat mengurangi penggunaan memori secara signifikan untuk output perintah besar seperti
ls -lR /, dan dalam beberapa kasus dapat memproses lebih cepat
- Contoh:
- Streaming parser tidak dapat digunakan bersama magic syntax
- Agar error parsing dalam pipeline yang berjalan lama tidak merusak pipe,
-qqatauignore_exceptions=Truedi Python dapat digunakan- Baris yang berhasil memuat
_jc_meta.success: true - Baris yang gagal memuat
_jc_meta.success: false, fielderror, danline
- Baris yang berhasil memuat
- Jika output tampak terlambat karena buffer sistem operasi di antara pipe, unbuffered output dapat digunakan dengan
-u- Namun, pada stream data besar, unbuffered output bisa lebih lambat
- Di Python, streaming parser menerima input iterable dan mengembalikan objek iterable sehingga dapat diproses secara lazy
Plugin Parser
- Parser plugin lokal dapat diletakkan di folder
jc/jcparserspada direktori data aplikasi- Linux/unix:
$HOME/.local/share/jc/jcparsers - macOS:
$HOME/Library/Application Support/jc/jcparsers - Windows:
$LOCALAPPDATA\jc\jc\jcparsers
- Linux/unix:
- Plugin adalah file modul Python standar
jc/parsers/foo.pyataujc/parsers/foo_s.pydapat digunakan sebagai template- Nama file plugin harus berupa nama modul Python yang valid, diawali huruf, dan hanya berisi karakter alfanumerik serta underscore
- Plugin lokal dapat menimpa parser bawaan
Locale, Zona Waktu, dan Kompatibilitas
- Untuk hasil terbaik, disarankan menyetel
LC_ALLkeCatauen_US.UTF-8 - Pada beberapa sistem lama, locale
Ctidak mendukung encoding UTF-8 sehingga output UTF-8 dapat turun menjadi ASCII dan escape sequence\\u - Beberapa parser menambahkan field epoch timestamp yang dihitung
- Jika nama field tidak memiliki suffix
_utc, field tersebut dianggap sebagai naive timestamp berbasis zona waktu lokal - Jika zona waktu UTC terdeteksi dari teks output perintah, timestamp menjadi timezone-aware dan nama key diberi suffix
_utc - Zona waktu selain UTC tidak didukung sebagai aware timestamp
- Jika nama field tidak memiliki suffix
- Beberapa parser mengonversi output spesifik platform, sehingga akan mencetak peringatan jika dijalankan pada platform yang tidak didukung
- File output dari sistem lain tetap dapat diparsing pada platform yang tidak didukung, dan dalam kasus ini peringatan dapat ditekan dengan
-qatauquiet=Truedi Python - Platform yang telah diuji mencakup Centos 7.7, Ubuntu 18.04/20.04, Fedora32, macOS 10.11.6/10.14.6, NixOS, FreeBSD12, Windows 10, Windows 2016 Server, dan Windows 2019 Server
1 komentar
Komentar Hacker News
Di FreeBSD, masalah ini sudah cukup banyak teratasi dengan libxo:
Keluaran terstruktur bisa didapat seperti
$ ps --libxo=json | jqMemang belum sempurna; dukungan untuk
lspernah ada tetapi dihapus karena suatu alasan, dan tidak semua utilitas mendukungnyajctampak seperti solusi sementara yang bagus karena menyediakan banyak parser perintah, tetapi tetap punya batasan karena mem-parsing keluaran teks yang sejak awal tidak dirancang untuk diparseAkan bagus jika berbagai utilitas berkumpul pada satu flag umum untuk mengeluarkan output terstruktur; meski menjadikannya default seperti PowerShell mungkin berlebihan untuk Unix/Linux, flag standar
--jsonsaja sudah menjadi kemajuan besarhttps://wiki.freebsd.org/LibXo
https://reviews.freebsd.org/D13959
Pemahaman saya, bukan sekadar meneruskan data terstruktur, melainkan mengalirkan objek opaque ke pipeline dan bahkan bisa kembali ke tahap sebelumnya untuk memanggil metode: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_methods?view=powershell-7.4
Saya juga menyukai wrapper seperti
jc,libxo, dan shell eksperimental seperti https://www.nushell.sh/, tetapi semuanya berfokus pada pengiriman data ketimbang objek yang memiliki metode yang bisa dieksekusiData terstruktur masih terasa Unix-like, dan menurut saya ketika benar-benar membutuhkan objek, itu saatnya menyalakan Python atau Ruby
Betapapun bagusnya shell dan fitur pemrogramannya, penting untuk tahu kapan harus beralih dari skrip shell ke bahasa pemrograman yang sungguh-sungguh
jcdiperkenalkan sebagai alat yang mengisi peran tersebut selama ini, dan tampaknya dimaksudkan sebagai jembatan sampai dukungan-j/--jsonmenyebar luas di seluruh tool Unixhttps://blog.kellybrazil.com/2019/11/26/bringing-the-unix-philosophy-to-the-21st-century/
/procmengembalikan data JSON, bukan file teks tak terstrukturSolusi yang lebih terstruktur mungkin adalah memungkinkan struktur data diekspor dari ELF, lalu menserialisasi struktur data itu menjadi keluaran terminal dan membiarkan pengguna mengeluarkan atau memprosesnya dalam format yang diinginkan seperti JSON atau YAML
Saya tidak ingat utilitas persisnya, mungkin
iostat, tetapi ia memformat baris keluaran JSON dengan interpolasi string dan pada kombinasi flag tertentu menghasilkan output yang benar-benar rusakSaya tidak tahu apakah sekarang sudah lebih baik, tetapi saat ada opsi interval, saya berharap bentuk seperti JSON lines
Dari sisi kegunaan, menurut saya PowerShell dan kubectl jauh lebih unggul daripada libxo
https://github.com/Juniper/libxo
https://libxo.readthedocs.io/en/latest/
Idenya sangat bagus, tetapi dari sisi pemeliharaan membuat saya khawatir
Jika mempertimbangkan versi, perubahan keluaran akibat flag perintah, dan sebagainya, ini tampak seperti neraka pemeliharaan; dalam penggunaan nyata mungkin berjalan baik pada beberapa kasus, tetapi setelah melewati contoh dasar rasanya kebaruannya akan cepat pudar
Selain itu, penggunaan
--untuk opsi alat juga tampak kurang bagusJika setiap parser baru membutuhkan flag baru, halaman bantuan atau manual bisa menjadi ribuan baris
Ketika suatu utilitas memutuskan mendukung ekspor JSON sendiri, setelah itu alat ini tinggal mendelegasikan ke fungsi tersebut
jcdi depan perintah, sepertijc lsParameter
--cmdjustru ide yang bagus karena memungkinkan data diolah sebelum dikonversiMisalnya, kita mungkin ingin melakukan
greppada daftar sebelum konversiDari sisi pemeliharaan juga, keluaran perintah Unix dasar jika berubah besar bukan hanya akan merusak alat ini, tetapi juga banyak sekali skrip, jadi sepertinya tidak akan sesering itu rusak karena pembaruan biner lain
Satu kumpulan parser bersama yang dikelola dengan baik lebih baik daripada parser keluaran ad hoc yang tersebar di mana-mana, tetapi dalam situasi ketika melakukan hal kompleks dan membutuhkan keluaran JSON langsung, saya berharap proses parsing itu sendiri tidak menambah masalah
Agar nyaman dipakai, pada akhirnya sepertinya saya tinggal mengirimkan test case tambahan sebagai PR untuk semua hal yang ingin saya gunakan
Toh test itu memang harus saya tulis sendiri
Satu-satunya jalan adalah orang-orang mengirimkan informasi parsing untuk alat yang mereka butuhkan, dan para pengguna menjaganya agar mudah tetap mutakhir
Nushell punya pendekatan yang berbeda, tetapi sebagian besar sampai di titik yang sama: data terstruktur dari perintah shell
Terutama dengan shell itu sendiri yang mengambil peran tersebut
http://www.nushell.sh/
from json, jadi sebenarnya cocok dipadukan dengan JCDulu saya merekam video yang menunjukkan beberapa fitur bagus Nushell, dan sekitar menit ke-19 membahas penggabungannya dengan
jc: https://www.youtube.com/watch?v=KF5dtxVsn1ESaat hendak menulis skrip untuk menelusuri file dalam direktori yang cocok dengan pola tertentu, lalu menghapus yang waktu modifikasinya berjarak kurang dari 10 menit satu sama lain, saya teringat bahwa Nushell bagus untuk pekerjaan seperti ini
Setelah mencobanya sebentar, akhirnya saya mulai mengerti, dan sekarang saya ketagihan
Bahkan data tidak terstruktur pun sangat kuat jika bisa diubah menjadi bentuk seperti daftar record untuk diproses
Dalam arti tertentu, fakta bahwa file ada di mana-mana itu luar biasa, dan itulah janji Unix; di Plan 9 bentuknya bahkan lebih diperluas
Namun file yang tidak terstruktur, atau setiap file memiliki formatnya sendiri-sendiri, juga sama-sama menghambat
Mencoba mem-parse satu file log nginx hanya dengan sesuatu seperti
awksaja bisa merepotkanSalah satu kelemahan besarnya adalah sulit menjalankan penulisan ulang sistem berskala besar atau perubahan desain di ruang pengguna Linux
Saya menginginkan shell yang lebih pintar, saya juga suka file, dan buku
awkada di sebelah saya, tetapi menurut saya sekarang saatnya ada perbaikan serius pada parsing dataAkan bagus kalau program bisa memutuskan apakah akan mengeluarkan output terstruktur, seperti halnya mereka bisa memutuskan apakah akan merender output berwarna atau tidak
Karena UI teks apa pun bisa digunakan seperti API, teks yang mudah dibaca manusia mendapat prioritas
Jadi scripting shell mirip dengan membuat ekstensi browser pihak ketiga
Kita melihat lalu menebak, kemudian buru-buru membuat parser berdasarkan tebakan itu dan berharap semuanya berjalan baik
Akan bagus kalau ada standard output ketiga untuk konten yang bisa dibaca mesin
Terminal tidak menampilkannya secara default, saat dipipe output inilah yang dipipe, formatnya harus JSONL, dan halaman manual menyatakan kontraknya
Dengan begitu standard output bisa tetap untuk manusia, dan parsing dilakukan dengan kesadaran bahwa itu mungkin tetapi rapuh
Tentu saja ini ide yang sepenuhnya memutus kompatibilitas mundur, dan kalau secara tidak realistis kita menciptakan ulang CLI dari dasar untuk memodernkannya, ada daftar panjang hal yang ingin saya ubah
Mendapatkan perbaikan juga benar-benar sulit, dan ketika orang seperti Lennart mencoba membersihkan sisa-sisa usang yang sudah berumur puluhan tahun, drama langsung terjadi
JSON juga belum sempurna
JSON adalah ide yang lumayan baik, tetapi untuk melakukannya dengan benar, kita butuh format yang bisa mengekspose hal-hal seperti tipe data
Pendekatannya harus lebih dekat ke PowerShell agar angka diperlakukan sebagai angka dan kita bisa melakukan hal menakjubkan seperti menghitung selisih tanggal dengan
$a - $bAkan bagus kalau ini terjadi di GNU coreutils
Masalahnya, ia terlalu mengakar dalam .NET dan objek, sehingga sangat sulit diintegrasikan dengan perintah native yang sudah ada di platform mana pun
Karena pada dasarnya ia sudah melakukan hal yang sama
Namun tujuan akhirnya tampaknya tetap agar tool tingkat atas melihat nilainya dan menyediakan output terstruktur secara langsung
Keren
Saya sangat mendukung tool CLI yang mendukung output JSON yang masuk akal, dan hal-hal seperti https://github.com/WireGuard/wireguard-tools/blob/master/contrib/json/wg-json serta
|ConvertTo-Jsonmilik PowerShell memegang peran besar dalam otomasi administrasi/pemantauanNamun kata masuk akal di sini memikul banyak beban, dan kenyataan tetaplah kenyataan
Seperti cara LSI/Broadcom StorCLI menambahkan
Jsetelah perintah, atau wrapper PowerShell yang menyembunyikan COM, secara teknis memang JSON, tetapi hasilnya luar biasa rumit atau tidak berguna, sehingga sering kali akhirnya kembali ke solusi sementara “sudah, jalankan regex sedikit pada output teks biasa saja”Meski begitu, saya pasti akan melihat ini
Kalau contoh pertama, parsing output
dig, mewakili sesuatu yang bisa dilakukan secara stabil, ini tampaknya cukup menarikMenurut saya
jc dig example.comseharusnya menjadi sintaks dasarKarena
dig example.com | jc --digharus menebak flag dan parameter dari perintah sebelumnya belakangan untuk mem-parse outputnyaFakta bahwa semua output adalah objek adalah salah satu bagian favorit saya dari PowerShell
Setiap kali harus menulis skrip bash, saya merindukannya
Hormat untuk orang yang memutuskan memelihara ini
Kalau bentuknya seperti
aws s3 ls | jc --aws=1.2.3, itu mimpi burukSaya jadi teringat program
filedi Linux atau Unix, dan para pahlawan yang memeliharanyaplugins, misalnya dalam bentuk perintah shell terpisah, sebagian upaya pemeliharaan bisa dialihkan ke penulis pluginSaya penasaran apakah ada yang tahu daftar tool command-line Unix modern yang menerima opsi
--jsonMenambahkan informasi semacam itu ke repositori ini juga bisa berguna
ip, pengganti modern untukifconfig, mendukung JSONlldpctljuga mendukungnyaAnsible menyediakan detail sistem sebagai JSON bernama
facts, dan memang dirancang agar otomasi dapat memanfaatkannyalsblkmenerima flag--jsondan bisa memberikan banyak informasiCoba jalankan
lsblk --json --output-allIni sangat berguna saat skrip perlu memeriksa disk dan partisi di sistem
-T jsonProyek yang menarik
Namun saya kira parser tahap pertamanya akan memakai sesuatu seperti textfsm
textfsm banyak dipakai untuk mem-parsing output CLI perangkat jaringan
https://github.com/google/textfsm