{"id":21461510,"url":"https://github.com/zix99/sshsysmon","last_synced_at":"2025-07-15T03:30:23.575Z","repository":{"id":42651937,"uuid":"52939020","full_name":"zix99/sshsysmon","owner":"zix99","description":"SSH System Monitoring -- Server monitoring over ssh for lazy people.","archived":false,"fork":false,"pushed_at":"2023-05-22T21:34:29.000Z","size":178,"stargazers_count":81,"open_issues_count":3,"forks_count":12,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-10T22:05:24.238Z","etag":null,"topics":["alerting","server-monitoring","ssh"],"latest_commit_sha":null,"homepage":"https://zix99.github.io/sshsysmon","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/zix99.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-02T06:18:41.000Z","updated_at":"2025-04-30T08:10:32.000Z","dependencies_parsed_at":"2023-02-05T03:46:13.838Z","dependency_job_id":null,"html_url":"https://github.com/zix99/sshsysmon","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/zix99/sshsysmon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zix99%2Fsshsysmon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zix99%2Fsshsysmon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zix99%2Fsshsysmon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zix99%2Fsshsysmon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zix99","download_url":"https://codeload.github.com/zix99/sshsysmon/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zix99%2Fsshsysmon/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265397504,"owners_count":23758443,"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":["alerting","server-monitoring","ssh"],"created_at":"2024-11-23T07:09:29.605Z","updated_at":"2025-07-15T03:30:23.151Z","avatar_url":"https://github.com/zix99.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unix System Monitoring Over SSH\n\n[![Build Status](https://travis-ci.org/zix99/sshsysmon.svg?branch=master)](https://travis-ci.org/zix99/sshsysmon)\n\nSshSysMon is a system/server monitoring tool that executes all of its operations over SSH without the\nneed for installing agents across machines.\n\nIts goal is to provide simple self-hosted monitoring and alerting for small numbers of lightweight\nservers without the traditional overhead of a monitoring system.\n\nIt monitors things in /proc and with simple command executions to monitor system vitals such as: memory, cpu load, drive space, swap, etc.\n\n\n![Html Dashboard](/examples/htmldash.jpg \"Example of the HTML Summary Output\")\n\n\n## Setup\n\n### Installation\n\n#### Via PyPi\n\n```bash\npip install sshsysmon\nsshmon --help\n```\n\n#### Via Docker\n\nThere is a docker image available on dockerhub based on alpine.\n\nIt can be run with the following:\n\n```bash\ndocker run -it zix99/sshsysmon summary examples/starter.yml\n```\n\nIf you have a config you wish to pass in, you can do so via a volume or swarm config.\n\n```bash\ndocker run -it -v config.yml:config.yml zix99/sshsysmon summary config.yml\n```\n\n#### Manually (No Install)\n\n```bash\n# Requires python 2.x and pip:\nsudo apt-get install -y python python-pip python-dev\n\n# Download the latest SshSysMon:\nwget -O - https://github.com/zix99/sshsysmon/archive/master.tar.gz | tar xzv\n\n# Make sure the dependencies are installed:\ncd sshsysmon-master/\npip install -r requirements.txt\n\n# Test it out!\n./sshmon summary examples/starter.yml\n```\n\n### Setting up a ssh key pair\n\n**You only need to do this if you are monitoring a remote server.**\n\nThe best way to connect to remote servers is with private key created and added to the `authorized_hosts` file on\nall systems you are interested in monitoring.  While password authentication is supported, this\nis the easiest way to guarantee continued authentication to other hosts.\n\nOn debian-based linux systems, setting up a key-pair to use with SSH is easy.  I would recommend\nyou make a new linux user to only do monitoring on each machine, but it isn't required.\n\n```bash\n# 1. Create a new SSH key if you don't already have one. Follow the prompts, but leave the password blank\nssh-keygen\n\n# 2. Install it on a user on another machine that you want to monitor\nssh-copy-id username@remotehost\n```\n\n\n### Running\n\nThe service has two commands, `summary` and `check`.\n\n#### Summary\n\n`summary` will print out a human-readable summary of all servers specified in the config. It is a\ngreat way to validate your config.\n\nIt can be executed with:\n\n    ./sshmon.py summary examples/starter.yml\n\nIt also can be told to use various templates. See templating section below. Eg, to use the html template:\n\n    ./sshmon.py -f html summary examples/starter.yml\n\n#### Check\n\n`check` is meant to be executed as part of a scheduled job, and will notify all channels in the config\nif a condition is unmet.\n\nIt can be excuted with:\n\n    ./sshmon.py check \u003cmyconfig.yml\u003e\n\n\n### Running Scheduled Job\n\nThe best way to run the service automatically is with a cron job.\n\nEdit your cron jobs with\n\n    crontab -e\n\nAdd an entry that runs the script every few hours: (or minutes, whatever you like)\n\n    0 */4 * * * /path/to/sshmon.py check /path/to/config.yml\n\n\n### Configuration\n\nConfiguration is written in yaml and is a set of servers, with a list of monitors with alarms,\nnotification channels and connection details.\n\nSee the [Examples](/examples) folder for more sample configs.\n\nAn example simple configuration might look something like this:\n\n```\nmeta: #Meta section (Optional). Used by summary templates\n  title: \"My Cluster Summary\"\n  author: \"Me\"\n\nservers:\n  \"Name of server\":\n    driver: ssh\n    config:\n      host: myhostname.com\n      username: myuser\n    channels: # Notification targets\n      - type: email\n        config:\n          toAddr: myemail@gmail.com\n          subject: \"Something went wrong on {server}\"\n    monitors: # All alerts and inspectors\n      - type: memory\n        alarms:\n          \"Low Swap\": \"swap_free.mb \u003c 50\"\n          \"Low Memory\": \"mem_free.mb \u003c 5\"\n      - type: disk\n        alarms:\n          \"Low Disk Space\": \"disk_free.gb \u003c 5\"\n        summarize: false # Optional, use if you don't want a monitor to show up in the summary\n```\n\nYou can often use YAML's inheritance to simplify your config for more than 1 server.  Each config section also\nhas a corresponding `+` version to add more in addition to something merged in.  eg. `monitors+`.\n\n\nAll servers are iterated through, and queried for given inspector types. The resulting `metrics` are compared to\nthe `alarms`, and if any of them are unmet, a notification it sent to all configured `channels`.\n\n#### Data Format\n\nAll sizes (that is, number of bytes), is enapsulated by the `ByteSize` class, which has helper methods for both friendly\noutput, and size casting in the form of `b`, `kb`, `mb`, etc.  eg, you can write `mem_free.mb \u003e 50`.\n\nAll timedelta's are encapsulated by the `TimeSpan` class, which has properties that expose reduced forms.\nThey are `seconds`, `minutes`, `hours`, and `days`.\n\nPercentages will always be presented in their 0-100 form.\n\n---\n\n## Application\n\n### Components\n\nThe applications is built on three components: `Drivers`, `Inspectors`, and `Channels`.\n\nEach has its corresponding folder with abstract implementation.  They are loaded dynamically with their\nname or path provided in the configuration.\n\n#### Drivers\n\nDrivers are classes that define how to read information from a server.  By default, there are two drivers:\n\n##### Local\n\nThe local driver is only for your local machine. There is no config for this driver.\n\n##### SSH\n\nThe SSH driver is for reaching out to remote machines.  There are several config paramters for this driver:\n\n  * host - The hostname of the machine (IP or Domain)\n  * username - The username to connect with\n  * password - (Not recommended, use key instead) The ssh user's password\n  * key - The path to the private key to use to connect (Default: ~/.ssh/id_rsa)\n  * port - The port to connect to the machine on (Default: 22)\n  * path - The path which proc is located (Default: /proc)\n\n--\n\n#### Channels\n\nChannels define what can happen if an alert fires.  There a few built-in.\n\nThere are a few variables passed in that can be used to format part of the commands:\n\n  * server - The server that the alert triggered on\n  * alert - The alert that triggered (the name)\n  * inspector - The inspector that triggered the alert\n  * statement - The statement of the inspector that fired the alert\n\n##### stdout\n\nWrites tab-separated data to stdout.  Can be appended to file with bash `\u003e\u003e` operator.\n\nArguments:\n\n  * timeFormat - Either `ctime` or `epoch`, the format which time is output. Default: `ctime`\n  * format - The format string used to write output. Default: `{time}\\t{server}\\t{inspector}\\t{alert}`\n\n##### command\n\nExecutes a shell command on the machine in which the script is running.\n\nArguments:\n\n  * command - The shell command to execute\n\n##### email\n\nSends an email via a SMTP server.\n\nBy default, it assumes a local SMTP server is setup.  For more complex configs, such as how to use\ngmail, see the examples.\n\nArguments:\n\n  * toAddr - The address to send the email to\n  * fromAddr - The address the email should come from (default: username@hostname)\n  * host - The SMTP host (default: localhost)\n  * port - The SMTP port (default: 25)\n  * subject - Subject line of email (has reasonable default)\n  * username - Username to authenticate with smtp server (default: none)\n  * password - Password to authenticate with smtp server (default: none)\n  * tls - Should use tls (default: false)\n  * ssl - Should use ssl (default: false)\n\n##### webhook\n\nCalls an http/https endpoint and passes it the JSON model.\n\nArguments:\n\n * url - The URL to call\n * method - The method to use in the http request (default: POST)\n * headers - A dict of any additional headers to add to the request\n * verifySSL - Whether or not to verify SSL cert (default: True)\n\n--\n\n#### Inspectors (Alert Types)\n\nInspects are parsers that know how to read data from a driver and make sense of it.\n\n##### Memory (memory)\n\nThe memory driver returns metrics about the systems memory:\n\nMetrics: mem_total, mem_free, cached, swap_total, swap_free\n\n##### Disk Space (disk)\n\nThe Disk driver returns status of the disk space (in GB)\n\nConfig:\n\n  * device - The name of the device (Optional, eg /dev/sda)\n  * mount - The mount point of the device (default: /)\n\nMetrics: size, used, available, percent_full\n\n##### Load Average (loadavg)\n\nThe load average inspector returns the system's current 1/5/15 minute [load average](http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages).\n\nMetrics: load_1m, load_5m, load_15m\n\n##### Process Monitor (process)\n\nThis inspector will allow you monitor a process on the given machine.\n\nIt takes in one **required** config `name`. This will use [wildcard matching](https://docs.python.org/2/library/fnmatch.html) with `*` and `?`.\n\nMetrics: user, pid, cpu, mem, tty\n\n##### TCP (tcp)\n\nThe TCP inspector will try to establish a connection on a given port with the same\nremote as the driver.  It's important to note that this does **not** go over SSH, and will\nnot verify anything more than that the port is willing to establish a connection.\n\nConfig:\n\n  * ports: A list, single port, or CSV of ports to check\n\nMetrics:\n\n  * A dictionary of the requested ports, prefixed with `port_`, and true if they are open, otherwise false (eg `port_22`)\n  * A special `all` metric which will be true if all ports are open\n\n##### HTTP (http)\n\nThe Http connector will attempt to do a GET request on a http/https endpoint, and return the data if able.\n\nConfig:\n\n  * path: The path to request on (default '/')\n  * port: The port to request at (default 80 for http, 443 for https)\n  * https: True/false if https (default: http)\n  * json: true/false if it should attempt to parse the response as json (Default: false)\n  * match: A regex to match against (default: None)\n\nMetrics:\n\n  * success: A true/false whether the request returns a 2xx, and all requirements were met (matches, or parses)\n  * match: Whether or not the regex matched. `None` if no match requested\n  * json: The parsed json, if requested\n  * url: The requested url\n\n##### Custom Command (exec)\n\n`exec` runs a custom command and returns `stdout`, `stderr`, and `status` (returncode).\n\nConfig:\n\n  * command: The shell command to execute\n  * environment: Optional object of environment variables (Default: {})\n  * json: Try to parse the command's output as json (Default: false)\n  * extract: Dict of name:path pairs to extract as metrics, eg `a.[1].c` (Default: None) See: Extracting Typed Json below; json must be `true`\n\nProperties extracted as metrics can be used in alarms\n\nMetrics:\n\n**If json, those will be the output metrics instead**\n\n  * stdout: The out string of the command\n  * stderr: The err string of the command\n  * status: The returncode of the command (0 means normal)\n\n##### File/Path Metadata (FileMeta)\n\n`filemeta` gathers all the metadata of all files in a path\n\nConfig:\n\n  * path: Path to gather the file data\n  * match: Matcher to select files within path\n  * maxDepth: The max depth it searches for files\n  * minDepth: The min depth it searches for files\n\nMetrics:\n\n  * count: Number of files that match\n  * oldest: The TimeSpan object of the oldest file\n  * newest: The TimeSpan object of the newest file\n  * largest: ByteSize of the largest file\n  * smallest: ByteSize of smallest file\n  * files: Array of files\n    * path: Path to the file\n    * size: ByteSize of the file\n    * last_access: access date\n    * last_modified: last modified time\n    * age: TimeSpan since last modified\n\n##### Networking Metrics (network)\n\n`network` gathers information about the network usage of system interfaces.\n\nConfig:\n\n  * match: Wildcard match to interface name (Default: None)\n  * hideEmpty: Hide interfaces that are empty (no traffic) (Default: False)\n\nMetrics:\n\n  * totals\n    * received\n    * tranmitted\n  * interfaces\n\n##### Core System Metrics (system)\n\nMetrics:\n\n  * uptime: TimeSpan of the time up\n  * idle: CPU time that is idle\n\n### Data\n\n#### Extracting Typed Objects\n\nIn cases where SshSysMon can parse and explore json applications, you might want to interpret data\nin a certain way. For example, it may be useful to grab a nested property and compute the TimeSpan\nfrom now.\n\nObject path selections are separated by `.`, and the optional type follows a `:`\n\nFor example, if you have this object:\n```json\n{\n  \"a\" : {\n    \"b\" : [\n      \"2018-12-15T15:57:17.619242731+01:00\"\n    ]\n  }\n}\n```\n\nAnd you wanted to extract the number of time that has passed between that date and now, your\nselector would be `a.b.[0]:TimeSpanFromNow`\n\nThe following types are supported:\n\n  * str: Convert object to string\n  * int: Convert object to int\n  * TimeSpan: Assume object is int number-of-seconds, and make TimeSpan\n  * TimeSpanFromNow: Assume object is parseable datetime, and compute TimeSpan between then and now\n  * DateTime: Parse string as datetime\n\n### Templating\n\nSshSysMon uses handlebars to template its summary output.  See the [templating](/templates) for more information.\n\n#### Prometheus\n\nSshSysMon supports writing to a format supported by prometheus, which can in-turn be pushed to a pushgateway via a pipe.\n\n```sh\nsshmon -f prometheus myconfig.yml | curl --data-binary @- http://prometheus.example.com/metrics/job/sshmon\n```\n\n### Writing Your Own Component\n\nTo learn how to write a specific type of component, visit its readme in the appropriate subfolder.\n\nAll components must define `def create(args):` as a well-known method to instantiate the class.  `args` will\nbe the configuration `dict` given in the configuration.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzix99%2Fsshsysmon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzix99%2Fsshsysmon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzix99%2Fsshsysmon/lists"}