{"id":15753678,"url":"https://github.com/dmotte/jctlfmt","last_synced_at":"2025-06-25T09:06:08.231Z","repository":{"id":65407792,"uuid":"591752023","full_name":"dmotte/jctlfmt","owner":"dmotte","description":"🐍 Python Journalctl parsing and formatting library","archived":false,"fork":false,"pushed_at":"2025-06-08T23:18:16.000Z","size":20,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-09T00:24:43.776Z","etag":null,"topics":["filtering","fmt","format","formatting","jctl","journal","journalctl","journald","log","logs","message","messages","msg","parsing","python","python-3","python3","systemd","systemd-journald","text"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/jctlfmt/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dmotte.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-01-21T18:50:38.000Z","updated_at":"2025-06-08T23:18:20.000Z","dependencies_parsed_at":"2023-02-12T13:16:05.720Z","dependency_job_id":"5c4f2a6f-4752-4a00-a6b9-be296d73dbc8","html_url":"https://github.com/dmotte/jctlfmt","commit_stats":{"total_commits":2,"total_committers":1,"mean_commits":2.0,"dds":0.0,"last_synced_commit":"736e683415edb8c283562f193ad68cdfdedca3af"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/dmotte/jctlfmt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotte%2Fjctlfmt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotte%2Fjctlfmt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotte%2Fjctlfmt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotte%2Fjctlfmt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmotte","download_url":"https://codeload.github.com/dmotte/jctlfmt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmotte%2Fjctlfmt/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261841956,"owners_count":23217913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filtering","fmt","format","formatting","jctl","journal","journalctl","journald","log","logs","message","messages","msg","parsing","python","python-3","python3","systemd","systemd-journald","text"],"created_at":"2024-10-04T07:41:41.801Z","updated_at":"2025-06-25T09:06:08.203Z","avatar_url":"https://github.com/dmotte.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jctlfmt\n\n[![GitHub main workflow](https://img.shields.io/github/actions/workflow/status/dmotte/jctlfmt/main.yml?branch=main\u0026logo=github\u0026label=main\u0026style=flat-square)](https://github.com/dmotte/jctlfmt/actions)\n[![PyPI](https://img.shields.io/pypi/v/jctlfmt?logo=python\u0026style=flat-square)](https://pypi.org/project/jctlfmt/)\n\n:snake: Python **Journalctl parsing** and **formatting** library.\n\nWith this library you can create custom scripts to **parse**, **filter** and **transform** data from **Journalctl** in a **human-friendly** format.\n\n## Installation\n\nThis library is available as a Python package on **PyPI**:\n\n```bash\npython3 -mpip install jctlfmt\n```\n\n## Usage\n\nYou can use the `jctlfmt.Entry` class in your code to **parse** _Journalctl_ messages from **JSON format** and then you can create **your own formatter class** by extending `jctlfmt.BaseFormatter` to filter and print the entries in the format you like.\n\nI have put a full usage example in the [`example`](example) folder of this repo. To try it you can use the following commands:\n\n```bash\nssh myuser@myserver.example.com \"sudo journalctl -ojson --output-fields _SOURCE_REALTIME_TIMESTAMP,__REALTIME_TIMESTAMP,_HOSTNAME,_SYSTEMD_UNIT,SYSLOG_IDENTIFIER,_PID,PRIORITY,MESSAGE -S '1 day ago'\" \u003e example/step01-json.txt\npython3 example/dedup.py \u003c example/step01-json.txt \u003e example/step02-dedup.txt\npython3 example/fmt.py \u003c example/step02-dedup.txt \u003e example/step03-fmt.txt\n```\n\nAs you can see I have two custom scripts: [`dedup.py`](example/dedup.py), which removes duplicate lines based on custom rules, and [`fmt.py`](example/fmt.py) which does the actual filtering and formatting.\n\nIn alternative, you can also use [`fmt.py`](example/fmt.py) to explore _Journalctl_ logs on the go:\n\n```bash\nsudo journalctl -ojson -ussh -S '1 day ago' | python3 example/fmt.py -fs | less\n```\n\nAs you can see, this time I invoked the script with `-fs` to disable filtering and sensitive mode. See `jctlfmt.BaseFormatter` for details.\n\nYou can customize [`fmt.py`](example/fmt.py) as you want and then use it in your setup. If you make modifications to the script and you want to test if the output is consistent, you can generate the output for all the possible invocations and then use `sha256sum` to check. The following commands may help:\n\n```bash\nfor i in '' -f -fs -s; do\n    python3 example/fmt.py $i \u003c example/step02-dedup.txt \u003e \"example/step03-arg$i.txt\"\ndone\nsha256sum example/step03-arg*.txt | sha256sum\n```\n\n## Development\n\nIf you want to contribute to this project, you can install the package in **editable** mode:\n\n```bash\npython3 -mpip install -e . --user\n```\n\nThis will just link the package to the original location, basically meaning any changes to the original package would reflect directly in your environment ([source](https://stackoverflow.com/a/35064498)).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmotte%2Fjctlfmt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmotte%2Fjctlfmt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmotte%2Fjctlfmt/lists"}