{"id":18057648,"url":"https://github.com/blob42/pswatch","last_synced_at":"2025-08-19T01:32:02.868Z","repository":{"id":250541627,"uuid":"834752673","full_name":"blob42/pswatch","owner":"blob42","description":"Execute custom commands for predefined system conditions ","archived":false,"fork":false,"pushed_at":"2025-07-18T21:23:05.000Z","size":111,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-18T21:53:42.860Z","etag":null,"topics":["executor","monitoring","process","resource-control","scheduler","task","timer"],"latest_commit_sha":null,"homepage":"https://git.blob42.xyz/blob42/pswatch","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blob42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["blob42"]}},"created_at":"2024-07-28T08:53:54.000Z","updated_at":"2025-07-18T21:24:05.000Z","dependencies_parsed_at":"2024-09-16T13:03:15.912Z","dependency_job_id":"5035dee6-56e8-43d9-9258-219a50408583","html_url":"https://github.com/blob42/pswatch","commit_stats":null,"previous_names":["blob42/pswatch"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/blob42/pswatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blob42%2Fpswatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blob42%2Fpswatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blob42%2Fpswatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blob42%2Fpswatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blob42","download_url":"https://codeload.github.com/blob42/pswatch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blob42%2Fpswatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271088026,"owners_count":24697039,"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","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["executor","monitoring","process","resource-control","scheduler","task","timer"],"created_at":"2024-10-31T02:08:50.367Z","updated_at":"2025-08-19T01:32:02.853Z","avatar_url":"https://github.com/blob42.png","language":"Rust","funding_links":["https://github.com/sponsors/blob42"],"categories":[],"sub_categories":[],"readme":" # PSWatch \n\nRun custom commands when defined system conditions are met.\n\npswatch is a minimalist process monitoring and task scheduler that allows you to\nwatch system processes and run custom commands when specific conditions or\npatterns are matched. \n\n**Features**\n- Process Matching: match running processes by substring or regex patterns in name, exe path or the entire command line.\n- Define conditions and actions. \n- Execute actions when conditions are met on the matched processes.\n- Create multiple profiles for complex conditions and action sets\n- Systemd `notify` process type integration.\n\n## Installation\n\n### From Crates.io\n\n`cargo install pswatch`\n\n### From source\n\n```sh\ngit clone https://github.com/blob42/pswatch.git\ncd pswatch\ncargo install --path .\n```\n\n## Usage\n\nPswatch requires a `TOML` based configuration file. By default it uses the config file under `$XDG_CONFIG_DIR/pswatch/config.toml` or the one provided as parameter.\n\n```sh\n./pswatch -c /path/to/config.toml\n```\n\nThe program will watch system processes and execute commands based on the\npatterns defined in the configuration file.\n\n## Configuration File\n\npswatch's behavior is configured using a TOML-formatted configuration file. The\nfile should contain a list of `profiles`, each containing a `matching` directive\n(the process to match), an (optional) `regex` flag (set to `true` if the\npattern is a regular expression), and a list of `commands`.\n\nEach command contains a condition (either `seen` or `not_seen` with a duration)\nand an array of shell commands (`exec`) to execute when the condition is met. An\noptional `run_once` flag can be set to run the command only once per process\ndetection.\n\nHere's an example configuration file:\n\n```toml\n[[profiles]]\nmatching = { name = \"foo\" }\n\n# command 1\n[[profiles.commands]]\ncondition = {seen = \"5s\"}\nexec = [\"sh\", \"-c\", \"notify-send psw 'foo action'\"]\n\n# command 2 \n[[profiles.commands]]\ncondition = { not_seen = \"60s\" }\nexec = [\"sh\", \"-c\", \"notify-send psw 'where is foo ?'\"]\nrun_once = true\n```\n\n## Example: Toggle Power Saving \n\nHere is a more realistic example that toggles the CPU turbo mode or power saving when a compilation job is detected: \n```toml\n[[profiles]]\n\n# matches common compilers for C,C++ and Rust\nmatching = { name = 'cc1.*|^cc$|gcc$|c\\+\\+$|c89$|c99$|cpp$|g\\+\\+$|rustc$', regex = true }\n\n[[profiles.commands]]\ncondition = {seen = \"3s\"}\n\n# command to execute when condition is met\nexec = [\"sh\", \"-c\", \"enable_turbo\"]\n\n# when exec_end is defined the schedule behaves like a toggle\n# command is executed when exiting the condition\nexec_end = [\"sh\", \"-c\",  \"disable_turbo\"]\n```\n\n## Example: dynamic nvidia-smi power profile for compute workloads\n\n```toml\n[[profiles]]\n\nmatching = { cmdline = \"llama.cpp|ollama runner|localai\", regex = true}\n\n[[profiles.commands]]\n\ncondition = {seen = \"1s\"}\nexec = [ \"sh\", \"-c\", \"sudo nvidia-smi -pl 280\" ]\n\n\n[[profiles.commands]]\n\ncondition = {not_seen = \"30s\"}\n\nexec = [ \"sh\", \"-c\", \"sudo nvidia-smi -pl 100\"]\n```\n\n## Examples with Multiple Profiles\n\nYou can use multiple profiles within a single configuration file to monitor different processes and execute commands for matched conditions.\nHere's an example configuration that uses two profiles:\n\n```toml\n[[profiles]]\npattern = \"bar\"\n\n# matches the process name\nmatching = { name = \"bar\" }\n\n[[profiles.commands]]\ncondition = {not_seen = \"5s\"}\nexec = [\"sh\", \"-c\", \"notify-send psw 'bar not seen!'\"]\n\n[[profiles]]\n# matches the full executable path\nmatching = { exe_path = '.*baz$', regex = true}\n\n[[profiles.commands]]\ncondition = {seen = \"10s\"}\nexec = [\"sh\", \"-c\", \"notify-send psw '/baz action !'\"]\nrun_once = true # run the command only once when a match is triggered\n\n\n[[profiles]]\n# matches the command line\nmatching = { cmdline = '\\-buz.*', regex = true}\n\n[[profiles.commands]]\ncondition = {seen = \"10s\"}\nexec = [\"sh\", \"-c\", \"notify-send psw 'someproc -buz action !'\"]\n\n```\n\nIn this example, pswatch will watch for three processes: \"bar\", \"baz\" and \"buz\". \n\n- It matches `bar` by process name (simple string).\n- Matches `.*baz$` and `\\-buz.*` by a regex pattern of the executable path and\ncommand line respectively.\n- When \"bar\" is not seen for 5 seconds, it will execute the `exec` action.\n- When \"baz\" (a regular expression) is detected, it will execute the\ncorresponding `exec` after a delay of 10 seconds.\n- The command for \"baz\" will be run only once per process detection.\n\n\n## Example Scenarios\n\n1. **Execute a command when a specific process is seen for a certain duration**\n   - Define a watch with the desired process name and use `{seen = \"duration\"}` to specify that the command should be executed when the process has been running for a specified duration (e.g., \"5s\").\n\n2. **Execute a command when a specific process is not seen for a certain duration**\n   - Define a watch with the desired process name and use `{not_seen = \"duration\"}` to specify that the command should be executed when the process has been absent for a specified duration (e.g., \"5s\").\n\n3. **Execute multiple commands based on different conditions**\n   - Define multiple watch configurations in the same TOML file and specify separate `condition` and `exec` settings for each. pswatch will monitor all configured profiles and execute their respective commands when appropriate.\n\n## Systemd User Unit\n```ini\n[Unit]\nDescription=pswatch process watcher\n\n[Service]\nType=notify\nExecStart=%h/.cargo/bin/pswatch\nRestart=on-failure\n; Use this to enable debug or trace\n;Environment=RUST_LOG=debug\n\n[Install]\nWantedBy=default.target\n\n```\n\n## Troubleshooting\n\nYou can enable more verbose output using the `-d` flag or setting the environment variable to `debug` or `trace`.\n\n## Contributing\n\nContributions are welcome ! If you'd like to contribute, please follow these steps:\n\n1. Fork the repository on GitHub.\n2. Clone your fork to your local machine: `git clone\n   https://github.com/your-username/pswatch.git`.\n   3. Create a new branch for your changes: `git checkout -b my-feature`.\n   4. Make your changes and commit them with descriptive messages:\n      `git commit -am 'Add some feature'`.\n   5. Push your branch: `git push origin my-feature`.\n   6. Submit a pull request from your GitHub fork to the main repository.\n\n## License\n\npswatch is licensed under the AGPLv3 License.\n\nSee [LICENSE](LICENSE) for more details.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblob42%2Fpswatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblob42%2Fpswatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblob42%2Fpswatch/lists"}