diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..defc6f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,125 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +#.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don’t work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +.vscode/ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e9b674c --- /dev/null +++ b/.python-version @@ -0,0 +1,3 @@ +3.6.12 +3.7.9 +3.9.0 diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..4cc92fe --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,9 @@ +version: 2 + +python: + version: 3.8 + install: + - requirements: requirements.txt + - method: setuptools + path: . + system_packages: true diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7593839 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,28 @@ +language: python + +install: +- pip install tox + +script: tox + +jobs: + include: + # - python: '3.6' + # env: TOXENV=py36 + # - python: '3.7' + # env: TOXENV=py37 + - python: '3.8' + env: TOXENV=py38 + # - python: '3.8' + # env: TOXENV=flake8 + - stage: deploy + script: echo "Deploying on PyPi ..." + env: + install: + deploy: + provider: pypi + user: JosefFriedrich + password: + secure: "SCcC+JzoJRrCR44wekJYIwqw3hJ+m9/EH68dyF3uwb6tErMQ9/hVkNnlc2sdQUsaOV4gr01OcMOO1AKfdlecIZVVw7GNxy3c4uyMSK720gNaGZok2Te46TGrT4EN7TPwZhcMI4aEdrnmw+18uhuyf7CACphcUTv2c3EimrKm57caNQJbPqs7wEk19fGNu+QLHkW+EGTy65px07Kr+a++1SpT1tr2gMjI5OJKzxuUA7afidFpwxtjon30MDSR1+bUUiuiAY26eJxGN41Qfak8N4QOgUEqKXXLOz1eZ4qQSy2gBFKKVZjkEGm0/D2hT85Wrq3IR/7l9XeCVrGXc7RKIK+R41m/xjkxwABDqYLu23ReAi51LNjUnuJL2LV5mQ0BLtBI5LJRhXrrejEXuoo6DV9x14YML65Xv8Z7btkRtVX7XAV3j8eIAegSe5jEuh0bIKPWNZU8zjC+xmflefJeUC7yEJ8XGv3MkK3cwCLCclu+XJP4hrfUinWeGFTADrwu4voB+CZhzcnp+3swyJRdVa6B8oeqWi/6FDaRMU3PNqNlpiaU5MvCg0FNossBw5a1xBLSqC++I6E+NiLC2W0Cw68YYAaDQCFapgfX1+OH9/xqKsMpJI2HdncGHTVlHgkjavd+91QOSyR5PiuxLx01gJS3Nha/sXvoq2l+0tCSEH0=" + on: + tags: true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8000a6f --- /dev/null +++ b/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random + Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..691de57 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include LICENSE +prune test +prune systemd_source_code \ No newline at end of file diff --git a/README-template.md b/README-template.md new file mode 100644 index 0000000..02cc1ec --- /dev/null +++ b/README-template.md @@ -0,0 +1,78 @@ +[![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd) +[![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd) + +# check_systemd + +`check_systemd` is a +[Nagios](https://www.nagios.org) / [Icinga](https://icinga.com) +monitoring plugin to check [systemd](https://systemd.io) for failed +units. + +This Python script will report a degraded system to your monitoring solution. +It requires only the +[nagiosplugin](https://nagiosplugin.readthedocs.io/en/stable) library. + +You can also test a single service with the `-u, --unit` parameter. + +## Installation + +``` +pip3 install check_systemd +``` + +## Command line interface + +``` +{{ argparse }} +``` + +## Project pages + +* https://github.com/Josef-Friedrich/check_systemd +* https://exchange.icinga.com/joseffriedrich/check_systemd +* https://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/check_systemd/details + +## Behind the scenes + +To detect failed units this monitoring script runs: + +```sh +systemctl list-units --all +``` + +To get the startup time it executes: + +```sh +systemd-analyze +``` + +To check a specific unit (`-u, --unit`) this command is executed: + +```sh +systemctl is-active +``` + +To find dead timers this plugin launches: + +```sh +systemctl list-timers --all +``` + +## Testing + +``` +pyenv install 3.6.12 +pyenv install 3.7.9 +pyenv local 3.6.12 3.7.9 +pip3 install tox +tox +``` + +## Deploying + +Edit version number in check_systemd.py (without `v`) + +``` +git tag v2.0.11 +git push --tags +``` diff --git a/README.md b/README.md new file mode 100644 index 0000000..66ae487 --- /dev/null +++ b/README.md @@ -0,0 +1,139 @@ +[![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd) +[![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd) + +# check_systemd + +`check_systemd` is a +[Nagios](https://www.nagios.org) / [Icinga](https://icinga.com) +monitoring plugin to check [systemd](https://systemd.io) for failed +units. + +This Python script will report a degraded system to your monitoring solution. +It requires only the +[nagiosplugin](https://nagiosplugin.readthedocs.io/en/stable) library. + +You can also test a single service with the `-u, --unit` parameter. + +## Installation + +``` +pip3 install check_systemd +``` + +## Command line interface + +``` +usage: check_systemd [-h] [-u UNIT | -e UNIT] [-n] [-w SECONDS] [-c SECONDS] + [-t] [-W SECONDS] [-C SECONDS] [-i] [-v] [-V] + +Copyright (c) 2014-18 Andrea Briganti a.k.a 'Kbyte' +Copyright (c) 2019-21 Josef Friedrich + +Nagios / Icinga monitoring plugin to check systemd. + +optional arguments: + -h, --help show this help message and exit + -u UNIT, --unit UNIT Name of the systemd unit that is being tested. + -e UNIT, --exclude UNIT + Exclude a systemd unit from the checks. This option can + be applied multiple times, for example: -e mnt- + data.mount -e task.service. Regular expressions can be + used to exclude multiple units at once, for example: -e + 'user@\d+\.service'. For more informations see the + Python documentation about regular expressions + (https://docs.python.org/3/library/re.html). + -n, --no-startup-time + Don’t check the startup time. Using this option the + options '-w, --warning' and '-c, --critical' have no + effect. Performance data about the startup time is + collected, but no critical, warning etc. states are + triggered. + -w SECONDS, --warning SECONDS + Startup time in seconds to result in a warning status. + Thedefault is 60 seconds. + -c SECONDS, --critical SECONDS + Startup time in seconds to result in a critical status. + Thedefault is 120 seconds. + -t, --dead-timers Detect dead / inactive timers. See the corresponding + options '-W, --dead-timer-warning' and '-C, --dead- + timers-critical'. Dead timers are detected by parsing + the output of 'systemctl list-timers'. Dead timer rows + displaying 'n/a' in the NEXT and LEFTcolumns and the + time span in the column PASSED exceeds the values + specified with the options '-W, --dead-timer-warning' + and '-C, --dead-timers-critical'. + -W SECONDS, --dead-timers-warning SECONDS + Time ago in seconds for dead / inactive timers to + trigger a warning state (by default 6 days). + -C SECONDS, --dead-timers-critical SECONDS + Time ago in seconds for dead / inactive timers to + trigger a critical state (by default 7 days). + -i, --ignore-inactive-state + Ignore an inactive state on a specific unit. Oneshot + services for example are only active while running and + not enabled. The rest of the time they are inactive. + This option has only an affect if it is used with the + option -u. + -v, --verbose Increase output verbosity (use up to 3 times). + -V, --version show program's version number and exit + +Performance data: + - count_units + - startup_time + - units_activating + - units_active + - units_failed + - units_inactive + +``` + +## Project pages + +* https://github.com/Josef-Friedrich/check_systemd +* https://exchange.icinga.com/joseffriedrich/check_systemd +* https://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/check_systemd/details + +## Behind the scenes + +To detect failed units this monitoring script runs: + +```sh +systemctl list-units --all +``` + +To get the startup time it executes: + +```sh +systemd-analyze +``` + +To check a specific unit (`-u, --unit`) this command is executed: + +```sh +systemctl is-active +``` + +To find dead timers this plugin launches: + +```sh +systemctl list-timers --all +``` + +## Testing + +``` +pyenv install 3.6.12 +pyenv install 3.7.9 +pyenv local 3.6.12 3.7.9 +pip3 install tox +tox +``` + +## Deploying + +Edit version number in check_systemd.py (without `v`) + +``` +git tag v2.0.11 +git push --tags +``` diff --git a/check_systemd.py b/check_systemd.py new file mode 100755 index 0000000..d75085a --- /dev/null +++ b/check_systemd.py @@ -0,0 +1,698 @@ +#!/usr/bin/env python3 + +""" +``check_system`` is a Nagios / Icinga monitoring plugin to check systemd. + +This plugin is based on a Python package named `nagiosplugin +`_. ``nagiosplugin`` has a fine-grained +class model to separate concerns. A Nagios / Icinga plugin need to perform +three steps: data `acquisition`, `evaluation` and `presentation`. +``nagiosplugin`` provides for this three steps three classes: ``Resource``, +``Context``, ``Summary``. ``check_systemd`` extends this three model classes in +the following subclasses: + +Acquisition (``Resource``) +========================== + +* :class:`SystemctlIsActiveResource` +* :class:`SystemctlListTimersResource` +* :class:`SystemctlListUnitsResource` +* :class:`SystemdAnalyseResource` + +Evaluation (``Context``) +======================== + +* :class:`DeadTimersContext` +* :class:`PerformanceDataContext` +* :class:`UnitContext` + +Presentation (``Summary``) +========================== + +* :class:`SystemdSummary` +""" +import io +import subprocess +import argparse +import re + +import nagiosplugin +from nagiosplugin import Metric + +__version__ = '2.3.0' + + +class SystemctlListUnitsResource(nagiosplugin.Resource): + """ + Resource that calls ``systemctl list-units --all`` on the command line to + get informations about all systemd units. + + :param list excludes: A list of systemd unit names. + """ + name = 'SYSTEMD' + + def __init__(self, excludes=[]): + self.excludes = excludes + + def re_match(self, unit): + for exclude in self.excludes: + if re.match(exclude, unit): + return(True) + return(False) + + def probe(self): + """Query system state and return metrics. + + :return: generator that emits + :class:`~nagiosplugin.metric.Metric` objects + """ + # We don’t use `systemctl --failed --no-legend`, because we want to + # collect performance data of all units. + try: + # p = subprocess.Popen(['./test/bin/ok/systemctl', 'list-units', '--all'], # noqa: E501 + p = subprocess.Popen(['systemctl', 'list-units', '--all'], + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + except OSError as e: + raise nagiosplugin.CheckError(e) + + if stderr: + raise nagiosplugin.CheckError(stderr) + + # Dictionary to store all units according their active state. + units = { + 'failed': [], + 'active': [], + 'activating': [], + 'inactive': [], + } + if stdout: + lines = stdout.decode('utf-8').splitlines() + table_heading = lines[0] + + # Remove the first line because it is the header. + + # Remove the last seven lines: + + # empty line + # LOAD = Reflects whether the unit definition... + # ACTIVE = The high-level unit activation state... + # SUB = The low-level unit activation state... + # empty line + # xxx loaded units listed. Pass --all to see ... + # To show all installed unit files use... + table_body = lines[1:-7] + table_parser = TableParser(table_heading) + # Output of `systemctl list-units --all: + # UNIT LOAD ACTIVE SUB JOB DESCRIPTION + # foobar.service loaded active waiting Description text + count_units = 0 + for line in table_body: + # foobar.service + unit = table_parser.get_column_text(line, 'UNIT') + # failed + active = table_parser.get_column_text(line, 'ACTIVE') + + # Only count not excluded units. + if not self.re_match(unit): + # Quick fix: + # Issue on Arch: “not-found” in column ACTIVE + # maybe cli table output changed on newer versions of + # systemd? + # maybe .split() is not working correctly? + if active not in units: + units[active] = [] + units[active].append(unit) + count_units += 1 + + for unit in units['failed']: + if not self.re_match(unit): + yield Metric(name=unit, value='failed', context='unit') + + for active, unit_names in units.items(): + yield Metric(name='units_{}'.format(active), + value=len(units[active]), + context='performance_data') + + yield Metric(name='count_units', value=count_units, + context='performance_data') + + if len(units['failed']) == 0: + yield Metric(name='all', value=None, context='unit') + + +def format_timespan_to_seconds(fmt_timespan): + """Convert a timespan format string into secondes. + + https://github.com/systemd/systemd/blob/master/src/basic/time-util.c#L357 + + :param str fmt_timespan: for example `2.345s` or `3min 45.234s` or + `34min left` or `2 months 8 days` + + :return: The seconds + :rtype: float + """ + for replacement in [ + ['years', 'y'], + ['months', 'month'], + ['weeks', 'w'], + ['days', 'd'], + ]: + fmt_timespan = fmt_timespan.replace( + ' ' + replacement[0], replacement[1] + ) + seconds = { + 'y': 31536000, # 365 * 24 * 60 * 60 + 'month': 2592000, # 30 * 24 * 60 * 60 + 'w': 604800, # 7 * 24 * 60 * 60 + 'd': 86400, # 24 * 60 * 60 + 'h': 3600, # 60 * 60 + 'min': 60, + 's': 1, + 'ms': 0.001, + } + result = 0 + for span in fmt_timespan.split(): + match = re.search(r'([\d\.]+)([a-z]+)', span) + if match: + value = match.group(1) + unit = match.group(2) + result += float(value) * seconds[unit] + return round(float(result), 3) + + +class SystemdAnalyseResource(nagiosplugin.Resource): + """Resource that calls ``systemd-analyze`` on the command line to get + informations about the startup time..""" + + name = 'SYSTEMD' + + def probe(self): + """Query system state and return metrics. + + :return: generator that emits + :class:`~nagiosplugin.metric.Metric` objects + """ + try: + p = subprocess.Popen(['systemd-analyze'], + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + except OSError as e: + raise nagiosplugin.CheckError(e) + + if stderr: + raise nagiosplugin.CheckError(stderr) + + if stdout: + stdout = stdout.decode('utf-8') + # First line: + # Startup finished in 1.672s (kernel) + 21.378s (userspace) = + # 23.050s + + # On raspian no second line + # Second line: + # graphical.target reached after 1min 2.154s in userspace + match = re.search(r'reached after (.+) in userspace', stdout) + + if not match: + match = re.search(r' = (.+)\n', stdout) + + # Output when boot process is not finished: + # Bootup is not yet finished. Please try again later. + if match: + yield Metric(name='startup_time', + value=format_timespan_to_seconds(match.group(1)), + context='startup_time') + + +class TableParser: + """A parser for the various table outputs of different systemd commands.""" + + def __init__(self, heading_row): + """ + :param str heading_row: A row with column titles. + """ + self.heading_row = heading_row + + def detect_column_boundaries(self, column_title): + """ + :param str column_title: The title of the column, for example UNIT, + ACTIVE. The column title must be included in the heading row. + """ + match = re.search(re.compile(column_title + r'\s*'), self.heading_row) + return [match.start(), match.end()] + + def get_column_text(self, row, column_title): + """Get the text of a certain column, that is specified by the column + title. Leading and trailing whitespaces are removed. + + :param str row: The current row of the table to extract a certain + column. + :param str column_title: The title of the column, for example UNIT, + ACTIVE. The column title must be included in the heading row. + """ + boundaries = self.detect_column_boundaries(column_title) + column = row[boundaries[0]:boundaries[1]] + return column.strip() + + +class SystemctlListTimersResource(nagiosplugin.Resource): + """ + Resource that calls ``systemctl list-timers --all`` on the command line to + get informations about dead / inactive timers. There is one type of systemd + “degradation” which is normally not detected: dead / inactive timers. + + :param list excludes: A list of systemd unit names to exclude from the + checks. + """ + def __init__(self, excludes=[], *args, **kwargs): + self.excludes = excludes + self.warning = kwargs.pop('warning') + self.critical = kwargs.pop('critical') + super().__init__(*args, **kwargs) + + name = 'SYSTEMD' + + column_names = [ + 'NEXT', 'LEFT', 'LAST', 'PASSED', 'UNIT', 'ACTIVATES' + ] + + column_boundaries = None + + def re_match(self, unit): + for exclude in self.excludes: + if re.match(exclude, unit): + return(True) + return(False) + + def detect_column_boundaries(self, heading): + boundaries = [] + previous_column_start = 0 + for column_title in self.column_names[1:]: + next_column_start = heading.index(column_title) + boundaries.append([previous_column_start, next_column_start]) + previous_column_start = next_column_start + return boundaries + + def get_column_text(self, row, column_name): + boundaries = self.column_boundaries[ + self.column_names.index(column_name) + ] + return row[boundaries[0]:boundaries[1]].strip() + + def probe(self): + """ + :return: generator that emits + :class:`~nagiosplugin.metric.Metric` objects + """ + try: + p = subprocess.Popen(['systemctl', 'list-timers', '--all'], + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + except OSError as e: + raise nagiosplugin.CheckError(e) + + if stderr: + raise nagiosplugin.CheckError(stderr) + + # NEXT LEFT + # Sat 2020-05-16 15:11:15 CEST 34min left + + # LAST PASSED + # Sat 2020-05-16 14:31:56 CEST 4min 20s ago + + # UNIT ACTIVATES + # apt-daily.timer apt-daily.service + if stdout: + lines = stdout.decode('utf-8').splitlines() + table_heading = lines[0] + self.column_boundaries = self.detect_column_boundaries( + table_heading + ) + # Remove the first line because it is the header. + # Remove the two last lines: empty line + "XX timers listed." + table_body = lines[1:-2] + + state = nagiosplugin.Ok # ok + + for row in table_body: + unit = self.get_column_text(row, 'UNIT') + if self.re_match(unit): + continue + next_date_time = self.get_column_text(row, 'NEXT') + + if next_date_time == 'n/a': + passed_text = self.get_column_text(row, 'PASSED') + + if passed_text == 'n/a': + state = nagiosplugin.Critical + else: + passed = format_timespan_to_seconds( + passed_text + ) + + if passed_text == 'n/a' or passed >= self.critical: + state = nagiosplugin.Critical + elif passed >= self.warning: + state = nagiosplugin.Warn + + yield Metric( + name=unit, + value=state, + context='dead_timers' + ) + + +class SystemctlIsActiveResource(nagiosplugin.Resource): + """Resource that calls ``systemctl is-active `` on the command + line to get informations about one specifiy systemd unit.""" + + name = 'SYSTEMD' + + def __init__(self, *args, **kwargs): + self.unit = kwargs.pop('unit') + super().__init__(*args, **kwargs) + + def probe(self): + """Query system state and return metrics. + + :return: generator that emits + :class:`~nagiosplugin.metric.Metric` objects + """ + # Execute `systemctl is-active ` and get output + # - active + # - inactive (by unkown unit file) + # - failed + try: + p = subprocess.Popen(['systemctl', 'is-active', self.unit], + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + except OSError as e: + raise nagiosplugin.CheckError(e) + + if stderr: + raise nagiosplugin.CheckError(stderr) + if stdout: + for line in io.StringIO(stdout.decode('utf-8')): + active = line.strip() + yield Metric(name=self.unit, value=active, context='unit') + + +class UnitContext(nagiosplugin.Context): + + def __init__(self, args): + self.args = args + super(UnitContext, self).__init__('unit') + + def evaluate(self, metric, resource): + """Determines state of a given metric. + + :param metric: associated metric that is to be evaluated + :param resource: resource that produced the associated metric + (may optionally be consulted) + :returns: :class:`~.result.Result` + """ + if metric.value: + hint = '{}: {}'.format(metric.name, metric.value) + else: + hint = metric.name + + # The option -u is not specifed + if not metric.value: + return self.result_cls(nagiosplugin.Ok, metric=metric, hint=hint) + + if self.args.ignore_inactive_state and metric.value == 'failed': + return self.result_cls(nagiosplugin.Critical, metric=metric, + hint=hint) + elif not self.args.ignore_inactive_state and metric.value != 'active': + return self.result_cls(nagiosplugin.Critical, metric=metric, + hint=hint) + else: + return self.result_cls(nagiosplugin.Ok, metric=metric, hint=hint) + + +class DeadTimersContext(nagiosplugin.Context): + + def __init__(self): + super(DeadTimersContext, self).__init__('dead_timers') + + def evaluate(self, metric, resource): + """Determines state of a given metric. + + :param metric: associated metric that is to be evaluated + :param resource: resource that produced the associated metric + (may optionally be consulted) + :returns: :class:`~.result.Result` + """ + return self.result_cls(metric.value, metric=metric, hint=metric.name) + + +class PerformanceDataContext(nagiosplugin.Context): + + def __init__(self): + super(PerformanceDataContext, self).__init__('performance_data') + + def performance(self, metric, resource): + """Derives performance data from a given metric. + + :param metric: associated metric from which performance data are + derived + :param resource: resource that produced the associated metric + (may optionally be consulted) + + :returns: :class:`Perfdata` object + """ + return nagiosplugin.Performance(label=metric.name, value=metric.value) + + +class SystemdSummary(nagiosplugin.Summary): + + def ok(self, results): + """Formats status line when overall state is ok. + + :param results: :class:`~nagiosplugin.result.Results` container + :returns: status line + """ + for result in results.most_significant: + if isinstance(result.context, UnitContext): + return '{0}'.format(result) + return 'all' + + def problem(self, results): + """Formats status line when overall state is not ok. + + :param results: :class:`~.result.Results` container + :returns: status line + """ + summary = [] + for result in results.most_significant: + if result.context.name in ['startup_time', 'unit', 'dead_timers']: + summary.append(result) + return ', '.join(['{0}'.format(result) for result in summary]) + + def verbose(self, results): + """Provides extra lines if verbose plugin execution is requested. + + :param results: :class:`~.result.Results` container + :returns: list of strings + """ + summary = [] + for result in results.most_significant: + if result.context.name in ['startup_time', 'unit', 'dead_timers']: + summary.append('{0}: {1}'.format(result.state, result)) + return summary + + +def get_argparser(): + parser = argparse.ArgumentParser( + prog='check_systemd', # To get the right command name in the README. + formatter_class=lambda prog: argparse.RawDescriptionHelpFormatter(prog, width=80), # noqa: E501 + description= # noqa: E251 + 'Copyright (c) 2014-18 Andrea Briganti a.k.a \'Kbyte\' \n' # noqa: E501 + 'Copyright (c) 2019-21 Josef Friedrich \n' + '\n' + 'Nagios / Icinga monitoring plugin to check systemd.\n', # noqa: E501 + epilog= # noqa: E251 + 'Performance data:\n' + ' - count_units\n' + ' - startup_time\n' + ' - units_activating\n' + ' - units_active\n' + ' - units_failed\n' + ' - units_inactive\n', + ) + + exclusive_group = parser.add_mutually_exclusive_group() + + exclusive_group.add_argument( + '-u', '--unit', + type=str, + dest='unit', + help='Name of the systemd unit that is being tested.', + ) + + exclusive_group.add_argument( + '-e', '--exclude', + metavar='UNIT', + action='append', + default=[], + help='Exclude a systemd unit from the checks. This option can be ' + 'applied multiple times, for example: -e mnt-data.mount -e ' + 'task.service. Regular expressions can be used to exclude ' + 'multiple units at once, for example: ' + '-e \'user@\\d+\\.service\'. ' + 'For more informations see the Python documentation about ' + 'regular expressions ' + '(https://docs.python.org/3/library/re.html).', + ) + + parser.add_argument( + '-n', '--no-startup-time', + action='store_true', + default=False, + help='Don’t check the startup time. Using this option the options ' + '\'-w, --warning\' and \'-c, --critical\' have no effect. ' + 'Performance data about the startup time is collected, but ' + 'no critical, warning etc. states are triggered.', + ) + + parser.add_argument( + '-w', '--warning', + default=60, + metavar='SECONDS', + help='Startup time in seconds to result in a warning status. The' + 'default is 60 seconds.', + ) + + parser.add_argument( + '-c', '--critical', + metavar='SECONDS', + default=120, + help='Startup time in seconds to result in a critical status. The' + 'default is 120 seconds.', + ) + + parser.add_argument( + '-t', '--dead-timers', + action='store_true', + help='Detect dead / inactive timers. See the corresponding options ' + '\'-W, --dead-timer-warning\' and ' + '\'-C, --dead-timers-critical\'. ' + 'Dead timers are detected by parsing the output of ' + '\'systemctl list-timers\'. ' + 'Dead timer rows displaying \'n/a\' in the NEXT and LEFT' + 'columns and the time span in the column PASSED exceeds the ' + 'values specified with the options \'-W, --dead-timer-warning\' ' + 'and \'-C, --dead-timers-critical\'.' + ) + + parser.add_argument( + '-W', '--dead-timers-warning', + metavar='SECONDS', + type=float, + default=60 * 60 * 24 * 6, + help='Time ago in seconds for dead / inactive timers to trigger a ' + 'warning state (by default 6 days).' + ) + + parser.add_argument( + '-C', '--dead-timers-critical', + metavar='SECONDS', + type=float, + default=60 * 60 * 24 * 7, + help='Time ago in seconds for dead / inactive timers to trigger a ' + 'critical state (by default 7 days).' + ) + + parser.add_argument( + '-i', '--ignore-inactive-state', + action='store_true', + help='Ignore an inactive state on a specific unit. Oneshot services ' + 'for example are only active while running and not enabled. ' + 'The rest of the time they are inactive. This option has only ' + 'an affect if it is used with the option -u.' + ) + + parser.add_argument( + '-v', '--verbose', + action='count', + default=0, + help='Increase output verbosity (use up to 3 times).' + ) + + parser.add_argument( + '-V', '--version', + action='version', + version='%(prog)s {}'.format(__version__), + ) + + return parser + + +def main(): + """The main function""" + args = get_argparser().parse_args() + + objects = [] + + if args.dead_timers: + objects += [ + SystemctlListTimersResource( + excludes=args.exclude, + warning=args.dead_timers_warning, + critical=args.dead_timers_critical, + ), + DeadTimersContext() + ] + + if args.unit: + objects.append(SystemctlIsActiveResource(unit=args.unit)) + else: + objects += [ + SystemctlListUnitsResource(excludes=args.exclude), + PerformanceDataContext(), + ] + analyse = subprocess.run( + ['systemd-analyze'], + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE + ) + # systemd-analyze: boot not finshed exits with 1 + if analyse.returncode == 0: + objects.append(SystemdAnalyseResource()) + + objects += [ + UnitContext(args), + SystemdSummary() + ] + + if not args.no_startup_time: + objects.append( + nagiosplugin.ScalarContext( + name='startup_time', + warning=args.warning, + critical=args.critical, + ) + ) + else: + objects.append( + nagiosplugin.ScalarContext( + name='startup_time' + ) + ) + + check = nagiosplugin.Check(*objects) + check.main(args.verbose) + + +if __name__ == '__main__': + main() diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..1732431 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,27 @@ +import sphinx_rtd_theme +import check_systemd + +html_theme = 'sphinx_rtd_theme' +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', +] +templates_path = ['_templates'] +source_suffix = '.rst' + +master_doc = 'index' + +project = u'check_systemd' +copyright = u'2020, Josef Friedrich' +author = u'Josef Friedrich' +version = check_systemd.__version__ +release = check_systemd.__version__ +language = None +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +pygments_style = 'sphinx' +todo_include_todos = False +html_static_path = [] +htmlhelp_basename = 'checksystemddoc' +autodoc_default_flags = ['members', 'undoc-members', 'private-members', 'show-inheritance'] diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..753bcaa --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,14 @@ +Welcome to check_systemd's documentation! +========================================= + +.. automodule:: check_systemd + :members: + :private-members: + :special-members: + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..961924f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +nagiosplugin>=1.2 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..224a779 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +description-file = README.md \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..bd29945 --- /dev/null +++ b/setup.py @@ -0,0 +1,64 @@ +import os +import re +from setuptools import setup, find_packages + +HERE = os.path.abspath(os.path.dirname(__file__)) + + +def read(*parts): + with open(os.path.join(HERE, *parts), 'r', encoding='utf-8') as fp: + return fp.read() + + +def find_version(*file_paths): + version_file = read(*file_paths) + version_match = re.search( + r"^__version__ = ['\"]([^'\"]*)['\"]", + version_file, + re.M, + ) + if version_match: + return version_match.group(1) + + raise RuntimeError("Unable to find version string.") + + +setup( + name='check_systemd', + packages=find_packages(), + version=find_version('check_systemd.py'), + scripts=['check_systemd.py'], + install_requires=[ + 'nagiosplugin>=1.2', + ], + description='Nagios / Icinga monitoring plugin to check systemd for ' + 'failed units.', + long_description=read('README.md'), + long_description_content_type='text/markdown', + author='Josef Friedrich', + author_email='josef@friedrich.rocks', + url='https://github.com/Josef-Friedrich/check_systemd', + keywords=['nagios', 'systemd'], + license='GNU LGPL v2', + python_requires='>=3.6', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Plugins', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: GNU Lesser General Public License v2 ' + '(LGPLv2)', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX :: Linux', + 'Topic :: System :: Networking :: Monitoring' + ], + entry_points={ + 'console_scripts': [ + 'check_systemd = check_systemd:main', + ], + }, +) diff --git a/test/bin/bootup_not_finished/systemctl b/test/bin/bootup_not_finished/systemctl new file mode 100755 index 0000000..5b22d7a --- /dev/null +++ b/test/bin/bootup_not_finished/systemctl @@ -0,0 +1,396 @@ +#! /bin/sh + +echo "UNIT LOAD ACTIVE SUB DESCRIPTION +mnt-nas.automount loaded active waiting Automount nnas +proc-sys-fs-binfmt_misc.automount loaded active waiting Arbitrary Executable File Formats File System Automount Point +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2dpartlabel-EFI\x5cx20System\x5cx20Partition.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2dpartuuid-1f489d33\x2db159\x2d43b0\x2dbb7b\x2d627b0f5257a6.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2dpartuuid-552a6e3d\x2d407e\x2d4766\x2d8108\x2d5d59b750e5c8.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2dpartuuid-bdf9e3c6\x2deac4\x2d46cc\x2d91cc\x2d82c4f67fce32.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2dpartuuid-edf6ea06\x2d605f\x2d4c5a\x2db6c1\x2d892fd24a6658.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2duuid-7B34B8C116E7DE4C.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2duuid-823483A534839B35.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2duuid-AE19\x2dC934.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2duuid-d924ad1b\x2d56c6\x2d4871\x2d9573\x2d208c8978c558.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-loop0.device loaded active plugged /dev/loop0 +dev-loop1.device loaded active plugged /dev/loop1 +dev-loop2.device loaded active plugged /dev/loop2 +dev-loop3.device loaded active plugged /dev/loop3 +dev-loop4.device loaded active plugged /dev/loop4 +dev-nvme0n1.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-nvme0n1p1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-nvme0n1p2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-nvme0n1p3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-nvme0n1p4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-rfkill.device loaded active plugged /dev/rfkill +dev-ttyprintk.device loaded active plugged /dev/ttyprintk +dev-ttyS0.device loaded active plugged /dev/ttyS0 +dev-ttyS1.device loaded active plugged /dev/ttyS1 +dev-ttyS10.device loaded active plugged /dev/ttyS10 +dev-ttyS11.device loaded active plugged /dev/ttyS11 +dev-ttyS12.device loaded active plugged /dev/ttyS12 +dev-ttyS13.device loaded active plugged /dev/ttyS13 +dev-ttyS14.device loaded active plugged /dev/ttyS14 +dev-ttyS15.device loaded active plugged /dev/ttyS15 +dev-ttyS16.device loaded active plugged /dev/ttyS16 +dev-ttyS17.device loaded active plugged /dev/ttyS17 +dev-ttyS18.device loaded active plugged /dev/ttyS18 +dev-ttyS19.device loaded active plugged /dev/ttyS19 +dev-ttyS2.device loaded active plugged /dev/ttyS2 +dev-ttyS20.device loaded active plugged /dev/ttyS20 +dev-ttyS21.device loaded active plugged /dev/ttyS21 +dev-ttyS22.device loaded active plugged /dev/ttyS22 +dev-ttyS23.device loaded active plugged /dev/ttyS23 +dev-ttyS24.device loaded active plugged /dev/ttyS24 +dev-ttyS25.device loaded active plugged /dev/ttyS25 +dev-ttyS26.device loaded active plugged /dev/ttyS26 +dev-ttyS27.device loaded active plugged /dev/ttyS27 +dev-ttyS28.device loaded active plugged /dev/ttyS28 +dev-ttyS29.device loaded active plugged /dev/ttyS29 +dev-ttyS3.device loaded active plugged /dev/ttyS3 +dev-ttyS30.device loaded active plugged /dev/ttyS30 +dev-ttyS31.device loaded active plugged /dev/ttyS31 +dev-ttyS4.device loaded active plugged /dev/ttyS4 +dev-ttyS5.device loaded active plugged /dev/ttyS5 +dev-ttyS6.device loaded active plugged /dev/ttyS6 +dev-ttyS7.device loaded active plugged /dev/ttyS7 +dev-ttyS8.device loaded active plugged /dev/ttyS8 +dev-ttyS9.device loaded active plugged /dev/ttyS9 +sys-devices-pci0000:00-0000:00:14.0-usb1-1\x2d8-1\x2d8:1.0-bluetooth-hci0.device loaded active plugged /sys/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/bluetooth/hci0 +sys-devices-pci0000:00-0000:00:1c.0-0000:01:00.0-0000:02:00.0-0000:03:00.0-domain0-0\x2d0-0\x2d1.device loaded active plugged /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/domain0/0-0/0-1 +sys-devices-pci0000:00-0000:00:1c.0-0000:01:00.0-0000:02:00.0-0000:03:00.0-domain0-0\x2d0.device loaded active plugged /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/domain0/0-0 +sys-devices-pci0000:00-0000:00:1c.0-0000:01:00.0-0000:02:00.0-0000:03:00.0-domain0.device loaded active plugged /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/domain0 +sys-devices-pci0000:00-0000:00:1c.5-0000:3a:00.0-net-wlp58s0.device loaded active plugged Wireless 8265 / 8275 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1.device loaded active plugged Samsung SSD 960 EVO 250GB +sys-devices-pci0000:00-0000:00:1f.3-sound-card0.device loaded active plugged Sunrise Point-LP HD Audio +sys-devices-pci0000:00-0000:00:1f.6-net-eno1.device loaded active plugged Ethernet Connection (4) I219-V +sys-devices-platform-serial8250-tty-ttyS0.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS0 +sys-devices-platform-serial8250-tty-ttyS1.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS1 +sys-devices-platform-serial8250-tty-ttyS10.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS10 +sys-devices-platform-serial8250-tty-ttyS11.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS11 +sys-devices-platform-serial8250-tty-ttyS12.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS12 +sys-devices-platform-serial8250-tty-ttyS13.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS13 +sys-devices-platform-serial8250-tty-ttyS14.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS14 +sys-devices-platform-serial8250-tty-ttyS15.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS15 +sys-devices-platform-serial8250-tty-ttyS16.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS16 +sys-devices-platform-serial8250-tty-ttyS17.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS17 +sys-devices-platform-serial8250-tty-ttyS18.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS18 +sys-devices-platform-serial8250-tty-ttyS19.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS19 +sys-devices-platform-serial8250-tty-ttyS2.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS2 +sys-devices-platform-serial8250-tty-ttyS20.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS20 +sys-devices-platform-serial8250-tty-ttyS21.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS21 +sys-devices-platform-serial8250-tty-ttyS22.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS22 +sys-devices-platform-serial8250-tty-ttyS23.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS23 +sys-devices-platform-serial8250-tty-ttyS24.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS24 +sys-devices-platform-serial8250-tty-ttyS25.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS25 +sys-devices-platform-serial8250-tty-ttyS26.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS26 +sys-devices-platform-serial8250-tty-ttyS27.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS27 +sys-devices-platform-serial8250-tty-ttyS28.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS28 +sys-devices-platform-serial8250-tty-ttyS29.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS29 +sys-devices-platform-serial8250-tty-ttyS3.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS3 +sys-devices-platform-serial8250-tty-ttyS30.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS30 +sys-devices-platform-serial8250-tty-ttyS31.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS31 +sys-devices-platform-serial8250-tty-ttyS4.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS4 +sys-devices-platform-serial8250-tty-ttyS5.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS5 +sys-devices-platform-serial8250-tty-ttyS6.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS6 +sys-devices-platform-serial8250-tty-ttyS7.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS7 +sys-devices-platform-serial8250-tty-ttyS8.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS8 +sys-devices-platform-serial8250-tty-ttyS9.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS9 +sys-devices-virtual-block-loop0.device loaded active plugged /sys/devices/virtual/block/loop0 +sys-devices-virtual-block-loop1.device loaded active plugged /sys/devices/virtual/block/loop1 +sys-devices-virtual-block-loop2.device loaded active plugged /sys/devices/virtual/block/loop2 +sys-devices-virtual-block-loop3.device loaded active plugged /sys/devices/virtual/block/loop3 +sys-devices-virtual-block-loop4.device loaded active plugged /sys/devices/virtual/block/loop4 +sys-devices-virtual-misc-rfkill.device loaded active plugged /sys/devices/virtual/misc/rfkill +sys-devices-virtual-tty-ttyprintk.device loaded active plugged /sys/devices/virtual/tty/ttyprintk +sys-module-configfs.device loaded active plugged /sys/module/configfs +sys-module-fuse.device loaded active plugged /sys/module/fuse +sys-subsystem-bluetooth-devices-hci0.device loaded active plugged /sys/subsystem/bluetooth/devices/hci0 +sys-subsystem-net-devices-eno1.device loaded active plugged Ethernet Connection (4) I219-V +sys-subsystem-net-devices-wlp58s0.device loaded active plugged Wireless 8265 / 8275 +-.mount loaded active mounted Root Mount +boot-efi.mount loaded active mounted /boot/efi +dev-hugepages.mount loaded active mounted Huge Pages File System +dev-mqueue.mount loaded active mounted POSIX Message Queue File System +mnt-ebook.mount loaded inactive dead Mount ebook +mnt-keepass.mount loaded inactive dead Mount keepass +mnt-lnas.mount loaded inactive dead Mount lnas +mnt-lnasdata.mount loaded inactive dead Mount lnasdata +mnt-nextcloudfirma.mount loaded inactive dead Automount /mnt/nextcloudfirma +mnt-nextcloudjf.mount loaded inactive dead Automount /mnt/nextcloudjf +mnt-nnas.mount loaded inactive dead Mount nnas +mnt-nnasdata.mount loaded inactive dead Mount nnasdata +mnt-wnas.mount loaded inactive dead Mount wnas +mnt-wnasdata.mount loaded inactive dead Mount wnasdata +proc-sys-fs-binfmt_misc.mount loaded inactive dead Arbitrary Executable File Formats File System +run-user-1000-gvfs.mount loaded active mounted /run/user/1000/gvfs +run-user-1000.mount loaded active mounted /run/user/1000 +run-user-121.mount loaded active mounted /run/user/121 +snap-core-5897.mount loaded active mounted Mount unit for core, revision 5897 +snap-core-6034.mount loaded active mounted Mount unit for core, revision 6034 +snap-core-6130.mount loaded active mounted Mount unit for core, revision 6130 +snap-filebot-16.mount loaded active mounted Mount unit for filebot, revision 16 +snap-filebot-9.mount loaded active mounted Mount unit for filebot, revision 9 +sys-fs-fuse-connections.mount loaded active mounted FUSE Control File System +sys-kernel-config.mount loaded active mounted Kernel Configuration File System +sys-kernel-debug.mount loaded active mounted Kernel Debug File System +tmp.mount not-found inactive dead tmp.mount +acpid.path loaded active running ACPI Events Check +apport-autoreport.path loaded active waiting Process error reports when automatic reporting is enabled (file watch) +cups.path loaded active running CUPS Scheduler +systemd-ask-password-console.path loaded inactive dead Dispatch Password Requests to Console Directory Watch +systemd-ask-password-plymouth.path loaded active waiting Forward Password Requests to Plymouth Directory Watch +systemd-ask-password-wall.path loaded active waiting Forward Password Requests to Wall Directory Watch +init.scope loaded active running System and Service Manager +session-2.scope loaded active running Session 2 of user jf +session-c1.scope loaded active running Session c1 of user gdm +accounts-daemon.service loaded active running Accounts Service +acpid.service loaded active running ACPI event daemon +alsa-restore.service loaded inactive dead Save/Restore Sound Card State +alsa-state.service loaded inactive dead Manage Sound Card State (restore and store) +anacron.service loaded inactive dead Run anacron jobs +apache2.service masked inactive dead apache2.service +apparmor.service masked inactive dead apparmor.service +apport-autoreport.service loaded inactive dead Process error reports when automatic reporting is enabled +apport.service loaded active exited LSB: automatic crash report generation +apt-daily-upgrade.service loaded inactive dead Daily apt upgrade and clean activities +apt-daily.service loaded inactive dead Daily apt download activities +auditd.service not-found inactive dead auditd.service +avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack +bind9.service loaded active running BIND Domain Name Server +blk-availability.service masked inactive dead blk-availability.service +bluetooth.service loaded active running Bluetooth service +bolt.service loaded active running Thunderbolt system service +certbot.service loaded inactive dead Certbot +cgroupfs-mount.service loaded active exited LSB: Set up cgroupfs mounts. +colord.service loaded active running Manage, Install and Generate Color Profiles +connman.service not-found inactive dead connman.service +console-screen.service not-found inactive dead console-screen.service +console-setup.service loaded active exited Set console font and keymap +containerd.service masked inactive dead containerd.service +cron.service loaded active running Regular background program processing daemon +cups.service loaded active running CUPS Scheduler +dbus.service loaded active running D-Bus System Message Bus +dfm-auto-jf.service loaded inactive dead dfm auto for user “jf” (dotfiles mangager auto update) +dfm-auto-root.service loaded inactive dead dfm auto for user “root” (dotfiles mangager auto update) +dns-clean.service loaded inactive dead Clean up any mess left by 0dns-up +docker.service masked inactive dead docker.service +ebtables.service masked inactive dead ebtables.service +emergency.service loaded inactive dead Emergency Shell +festival.service not-found inactive dead festival.service +fstrim.service loaded inactive dead Discard unused blocks +fwupd.service loaded active running Firmware update daemon +gdm.service loaded active running GNOME Display Manager +getty-static.service loaded inactive dead getty on tty2-tty6 if dbus and logind are not available +getty@tty1.service loaded inactive dead Getty on tty1 +gitup.service loaded inactive dead Run gitup (git-repo-updater) +google-fonts.service loaded inactive dead Google fonts update +gpu-manager.service loaded inactive dead Detect the available GPUs and deal with any system changes +grub-common.service loaded active exited LSB: Record successful boot for GRUB +hblock.service loaded inactive dead hBlock update (/etc/hosts) +irqbalance.service loaded active running irqbalance daemon +jfddns-update-script_nuc_dev-eno1_ipvboth.service loaded inactive dead jfddns-update-script.sh (nuc_dev-eno1_ipvboth) +kbd.service not-found inactive dead kbd.service +kerneloops.service loaded active running Tool to automatically collect and submit kernel crash signatures +keyboard-setup.service loaded active exited Set the console keyboard layout +kmod-static-nodes.service loaded active exited Create list of required static device nodes for the current kernel +libvirt-guests.service masked inactive dead libvirt-guests.service +libvirtd.service masked inactive dead libvirtd.service +lively-lights.service not-found inactive dead lively-lights.service +lvm2-lvmetad.service loaded active exited LSB: LVM2 metadata daemon +lvm2-lvmpolld.service loaded active exited LSB: LVM2 poll daemon +lvm2-monitor.service masked inactive dead lvm2-monitor.service +mariadb.service loaded active running MariaDB 10.1.38 database server +ModemManager.service loaded active running Modem Manager +mysqldump-all.service loaded inactive dead mysqldump-all +networkd-dispatcher.service loaded active running Dispatcher daemon for systemd-networkd +networking.service loaded active exited Raise network interfaces +NetworkManager-wait-online.service loaded active exited Network Manager Wait Online +NetworkManager.service loaded active running Network Manager +nginx.service loaded active running A high performance web server and a reverse proxy server +nmbd.service loaded active running Samba NMB Daemon +nsca-localhost.service loaded inactive dead NSCA localhost +oem-config.service not-found inactive dead oem-config.service +ondemand.service loaded inactive dead Set the CPU Frequency Scaling governor +openvpn.service masked inactive dead openvpn.service +packagekit.service loaded active running PackageKit Daemon +php7.2-fpm.service loaded active running The PHP 7.2 FastCGI Process Manager +phpsessionclean.service loaded inactive dead Clean php session files +plymouth-quit-wait.service loaded inactive dead Hold until boot process finishes up +plymouth-quit.service loaded inactive dead Terminate Plymouth Boot Screen +plymouth-read-write.service loaded inactive dead Tell Plymouth To Write Out Runtime Data +plymouth-start.service loaded inactive dead Show Plymouth Boot Screen +polkit.service loaded active running Authorization Manager +postfix.service masked inactive dead postfix.service +pppd-dns.service loaded inactive dead Restore /etc/resolv.conf if the system crashed before the ppp link was shut down +qemu-kvm.service loaded active exited QEMU KVM preparation - module, ksm, hugepages +rc-local.service loaded inactive dead /etc/rc.local Compatibility +rescue.service loaded inactive dead Rescue Shell +resolvconf.service not-found inactive dead resolvconf.service +rsync.service loaded inactive dead fast remote file copy program daemon +rsyslog.service loaded active running System Logging Service +rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy Service +setvtrgb.service loaded active exited Set console scheme +smartd.service masked inactive dead smartd.service +smbd.service loaded active running Samba SMB Daemon +snapd.autoimport.service masked inactive dead snapd.autoimport.service +snapd.core-fixup.service masked inactive dead snapd.core-fixup.service +snapd.seeded.service masked inactive dead snapd.seeded.service +snapd.service masked inactive dead snapd.service +speech-dispatcher.service loaded active exited LSB: Speech Dispatcher +ssh.service loaded active running OpenBSD Secure Shell server +systemd-ask-password-console.service loaded inactive dead Dispatch Password Requests to Console +systemd-ask-password-plymouth.service loaded inactive dead Forward Password Requests to Plymouth +systemd-ask-password-wall.service loaded inactive dead Forward Password Requests to Wall +systemd-binfmt.service loaded inactive dead Set Up Additional Binary Formats +systemd-fsck-root.service loaded inactive dead File System Check on Root Device +systemd-fsck@dev-disk-by\x2duuid-AE19\x2dC934.service loaded active exited File System Check on /dev/disk/by-uuid/AE19-C934 +systemd-fsckd.service loaded inactive dead File System Check Daemon to report status +systemd-hwdb-update.service loaded inactive dead Rebuild Hardware Database +systemd-initctl.service loaded inactive dead /dev/initctl Compatibility Daemon +systemd-journal-flush.service loaded active exited Flush Journal to Persistent Storage +systemd-journald.service loaded active running Journal Service +systemd-logind.service loaded active running Login Service +systemd-machine-id-commit.service loaded inactive dead Commit a transient machine-id on disk +systemd-modules-load.service loaded active exited Load Kernel Modules +systemd-networkd.service loaded inactive dead Network Service +systemd-quotacheck.service loaded inactive dead File System Quota Check +systemd-random-seed.service loaded active exited Load/Save Random Seed +systemd-remount-fs.service loaded active exited Remount Root and Kernel File Systems +systemd-resolved.service loaded active running Network Name Resolution +systemd-rfkill.service loaded inactive dead Load/Save RF Kill Switch Status +systemd-sysctl.service loaded active exited Apply Kernel Variables +systemd-sysusers.service not-found inactive dead systemd-sysusers.service +systemd-timesyncd.service loaded active running Network Time Synchronization +systemd-tmpfiles-clean.service loaded inactive dead Cleanup of Temporary Directories +systemd-tmpfiles-setup-dev.service loaded active exited Create Static Device Nodes in /dev +systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories +systemd-udev-trigger.service loaded active exited udev Coldplug all Devices +systemd-udevd.service loaded active running udev Kernel Device Manager +systemd-update-done.service not-found inactive dead systemd-update-done.service +systemd-update-utmp-runlevel.service loaded inactive dead Update UTMP about System Runlevel Changes +systemd-update-utmp.service loaded active exited Update UTMP about System Boot/Shutdown +systemd-user-sessions.service loaded active exited Permit User Sessions +systemd-vconsole-setup.service not-found inactive dead systemd-vconsole-setup.service +texlive-update.service loaded inactive dead TeXlive update +thermald.service loaded active running Thermal Daemon Service +tor.service loaded active exited Anonymizing overlay network for TCP (multi-instance-master) +tor@default.service loaded active running Anonymizing overlay network for TCP +udisks2.service loaded active running Disk Manager +ufw.service loaded active exited Uncomplicated firewall +unattended-upgrades-frequent.service loaded inactive dead unattended-upgrades +unattended-upgrades.service loaded active running Unattended Upgrades Shutdown +update-motd.service loaded inactive dead Run update-motd and generate /var/run/motd +upower.service loaded active running Daemon for power management +ureadahead-stop.service loaded inactive dead Stop ureadahead data collection +ureadahead.service loaded inactive dead Read required files in advance +user@1000.service loaded active running User Manager for UID 1000 +user@121.service loaded active running User Manager for UID 121 +uuidd.service loaded active running Daemon for generating UUIDs +vnstat.service loaded active exited LSB: lightweight network traffic monitor +vsftpd.service loaded active running vsftpd FTP server +whoopsie.service loaded active running crash report submission daemon +winbind.service not-found inactive dead winbind.service +wpa_supplicant.service loaded active running WPA supplicant +-.slice loaded active active Root Slice +system-getty.slice loaded active active system-getty.slice +system-systemd\x2dfsck.slice loaded active active system-systemd\x2dfsck.slice +system-tor.slice loaded active active system-tor.slice +system.slice loaded active active System Slice +user-1000.slice loaded active active User Slice of jf +user-121.slice loaded active active User Slice of gdm +user.slice loaded active active User and Session Slice +acpid.socket loaded active running ACPID Listen Socket +avahi-daemon.socket loaded active running Avahi mDNS/DNS-SD Stack Activation Socket +cups.socket loaded active running CUPS Scheduler +dbus.socket loaded active running D-Bus System Message Bus Socket +dm-event.socket masked inactive dead dm-event.socket +docker.socket not-found inactive dead docker.socket +lvm2-lvmetad.socket masked inactive dead lvm2-lvmetad.socket +lvm2-lvmpolld.socket masked inactive dead lvm2-lvmpolld.socket +snapd.socket masked inactive dead snapd.socket +syslog.socket loaded active running Syslog Socket +systemd-fsckd.socket loaded active listening fsck to fsckd communication Socket +systemd-initctl.socket loaded active listening /dev/initctl Compatibility Named Pipe +systemd-journald-audit.socket loaded active running Journal Audit Socket +systemd-journald-dev-log.socket loaded active running Journal Socket (/dev/log) +systemd-journald.socket loaded active running Journal Socket +systemd-rfkill.socket loaded active listening Load/Save RF Kill Switch Status /dev/rfkill Watch +systemd-udevd-control.socket loaded active running udev Control Socket +systemd-udevd-kernel.socket loaded active running udev Kernel Socket +uuidd.socket loaded active running UUID daemon activation socket +virtlockd.socket masked inactive dead virtlockd.socket +virtlogd.socket masked inactive dead virtlogd.socket +swapfile.swap loaded active active /swapfile +all.target not-found inactive dead all.target +basic.target loaded active active Basic System +bluetooth.target loaded active active Bluetooth +cryptsetup.target loaded active active Local Encrypted Volumes +emergency.target loaded inactive dead Emergency Mode +getty-pre.target loaded inactive dead Login Prompts (Pre) +getty.target loaded active active Login Prompts +graphical.target loaded active active Graphical Interface +local-fs-pre.target loaded active active Local File Systems (Pre) +local-fs.target loaded active active Local File Systems +multi-user.target loaded active active Multi-User System +network-online.target loaded active active Network is Online +network-pre.target loaded inactive dead Network (Pre) +network.target loaded active active Network +nss-lookup.target loaded active active Host and Network Name Lookups +nss-user-lookup.target loaded active active User and Group Name Lookups +paths.target loaded active active Paths +remote-fs-pre.target loaded inactive dead Remote File Systems (Pre) +remote-fs.target loaded active active Remote File Systems +rescue.target loaded inactive dead Rescue Mode +shutdown.target loaded inactive dead Shutdown +slices.target loaded active active Slices +sockets.target loaded active active Sockets +sound.target loaded active active Sound Card +swap.target loaded active active Swap +sysinit.target loaded active active System Initialization +syslog.target not-found inactive dead syslog.target +time-sync.target loaded active active System Time Synchronized +timers.target loaded active active Timers +umount.target loaded inactive dead Unmount All Filesystems +anacron.timer loaded active waiting Trigger anacron every hour +apt-daily-upgrade.timer loaded active waiting Daily apt upgrade and clean activities +apt-daily.timer loaded active waiting Daily apt activities +certbot.timer loaded active waiting Run certbot twice daily +fstrim.timer loaded active waiting Discard unused blocks once a week +motd-news.timer masked inactive dead motd-news.timer +mysqldump-all.timer loaded active waiting mysqldump-all +nsca-localhost.timer loaded active waiting NSCA localhost +nsupdate-nuc.jf-dyndns.cf.timer not-found inactive dead nsupdate-nuc.jf-dyndns.cf.timer +phpsessionclean.timer loaded active waiting Clean PHP session files every 30 mins +snapd.refresh.timer not-found inactive dead snapd.refresh.timer +snapd.snap-repair.timer masked inactive dead snapd.snap-repair.timer +systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories +unattended-upgrades-frequent.timer loaded active waiting unattended-upgrades +update-motd.timer loaded active waiting Run update-motd and generate /var/run/motd +ureadahead-stop.timer loaded active elapsed Stop ureadahead data collection 45s after completed startup + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'." diff --git a/test/bin/bootup_not_finished/systemd-analyze b/test/bin/bootup_not_finished/systemd-analyze new file mode 100755 index 0000000..fceaa16 --- /dev/null +++ b/test/bin/bootup_not_finished/systemd-analyze @@ -0,0 +1,5 @@ +#! /bin/sh + +echo "Bootup is not yet finished. Please try again later." + +exit 1 diff --git a/test/bin/dead_timers_1/systemctl b/test/bin/dead_timers_1/systemctl new file mode 100755 index 0000000..e3ea567 --- /dev/null +++ b/test/bin/dead_timers_1/systemctl @@ -0,0 +1,29 @@ +#! /bin/sh + +case $@ in + 'list-units --all') + echo "UNIT LOAD ACTIVE SUB DESCRIPTION +sockets.target loaded active active Sockets +sound.target loaded active active Sound Card +swap.target loaded active active Swap + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'."; + exit 0 + ;; + + 'list-timers --all') + echo "NEXT LEFT LAST PASSED UNIT ACTIVATES +Sat 2020-05-16 23:34:57 CEST 20h left Fri 2020-05-15 23:34:57 CEST 3h 39min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service +n/a n/a Thu 2020-03-12 03:09:01 CET 2 months 4 days ago phpsessionclean.timer phpsessionclean.service + +2 timers listed."; + exit 0 + ;; + +esac +echo diff --git a/test/bin/dead_timers_1/systemd-analyze b/test/bin/dead_timers_1/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/dead_timers_1/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/dead_timers_2/systemctl b/test/bin/dead_timers_2/systemctl new file mode 100755 index 0000000..74fc681 --- /dev/null +++ b/test/bin/dead_timers_2/systemctl @@ -0,0 +1,41 @@ +#! /bin/sh + +case $@ in + 'list-units --all') + echo "UNIT LOAD ACTIVE SUB DESCRIPTION +sockets.target loaded active active Sockets +sound.target loaded active active Sound Card +swap.target loaded active active Swap + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'."; + exit 0 + ;; + + 'list-timers --all') + echo "NEXT LEFT LAST PASSED UNIT ACTIVATES +Sat 2020-05-16 11:26:47 CEST 1min 26s left Sat 2020-05-16 11:24:21 CEST 58s ago dyndns-update-script_nuernberg_dev-eth0_ipv4.timer dyndns-update-script_nuernberg_dev-eth0_ipv4.service +Sat 2020-05-16 11:27:01 CEST 1min 40s left Sat 2020-05-16 11:23:44 CEST 1min 36s ago nsca-localhost.timer nsca-localhost.service +Sat 2020-05-16 11:27:39 CEST 2min 19s left Sat 2020-05-16 11:25:14 CEST 6s ago dyndns-update-script_nrasp_dev-eth0_ipvboth.timer dyndns-update-script_nrasp_dev-eth0_ipvboth.service +Sat 2020-05-16 11:30:00 CEST 4min 39s left Sat 2020-05-16 09:00:00 CEST 2h 25min ago turn-on.timer turn-on.service +Sat 2020-05-16 11:46:11 CEST 20min left Sat 2020-05-16 10:41:47 CEST 43min ago unattended-upgrades-frequent.timer unattended-upgrades-frequent.service +Sat 2020-05-16 12:01:43 CEST 36min left Sat 2020-05-16 11:01:06 CEST 24min ago dfm-auto-root.timer dfm-auto-root.service +Sat 2020-05-16 12:02:32 CEST 37min left Sat 2020-05-16 11:00:42 CEST 24min ago anacron.timer anacron.service +Sat 2020-05-16 16:30:13 CEST 5h 4min left Fri 2020-05-15 16:30:13 CEST 18h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service +Sat 2020-05-16 18:52:48 CEST 7h left Sat 2020-05-16 10:28:05 CEST 57min ago apt-daily.timer apt-daily.service +Sun 2020-05-17 00:00:00 CEST 12h left Sat 2020-05-16 00:00:00 CEST 11h ago gitserver-manager.timer gitserver-manager.service +Sun 2020-05-17 00:00:00 CEST 12h left Sat 2020-05-16 00:00:00 CEST 11h ago oh-my-zsh_jf.timer oh-my-zsh_jf.service +Sun 2020-05-17 00:00:00 CEST 12h left Sat 2020-05-16 00:00:00 CEST 11h ago oh-my-zsh_root.timer oh-my-zsh_root.service +Sun 2020-05-17 06:23:17 CEST 18h left Sat 2020-05-16 06:16:55 CEST 5h 8min ago apt-daily-upgrade.timer apt-daily-upgrade.service +n/a n/a Tue 2020-04-07 05:49:00 CEST 1 months 1 days ago dfm-auto-jf.timer dfm-auto-jf.service +n/a n/a Tue 2020-04-07 04:17:32 CEST 1 months 2 days ago rsync.timer rsync.service + +15 timers listed."; + exit 0 + ;; + +esac diff --git a/test/bin/dead_timers_2/systemd-analyze b/test/bin/dead_timers_2/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/dead_timers_2/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/dead_timers_ok/systemctl b/test/bin/dead_timers_ok/systemctl new file mode 100755 index 0000000..f50bde2 --- /dev/null +++ b/test/bin/dead_timers_ok/systemctl @@ -0,0 +1,31 @@ +#! /bin/sh + +case $@ in + 'list-units --all') + echo "UNIT LOAD ACTIVE SUB DESCRIPTION +sockets.target loaded active active Sockets +sound.target loaded active active Sound Card +swap.target loaded active active Swap + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'."; + exit 0 + ;; + + 'list-timers --all') + echo "NEXT LEFT LAST PASSED UNIT ACTIVATES + hblock.service +Sat 2020-05-16 14:37:33 CEST 1min 16s left Sat 2020-05-16 14:32:27 CEST 3min 49s ago update-motd.timer update-motd.service +Sat 2020-05-16 14:50:58 CEST 14min left Sat 2020-05-16 14:31:56 CEST 4min 20s ago rsync_nnas_data-shares-jf-maps_wnas-data-shares-jf-maps.timer rsync_nnas_data-shares-jf-maps_wnas-data-shares-jf-maps.service +Sat 2020-05-16 15:03:13 CEST 26min left Sat 2020-05-16 14:31:56 CEST 4min 20s ago anacron.timer anacron.service +Sat 2020-05-16 15:11:15 CEST 34min left Sat 2020-05-16 14:31:56 CEST 4min 20s ago apt-daily.timer apt-daily.service + +5 timers listed."; + exit 0 + ;; + +esac diff --git a/test/bin/dead_timers_ok/systemd-analyze b/test/bin/dead_timers_ok/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/dead_timers_ok/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/failure/systemctl b/test/bin/failure/systemctl new file mode 100755 index 0000000..dfcaa37 --- /dev/null +++ b/test/bin/failure/systemctl @@ -0,0 +1,13 @@ +#! /bin/sh + +echo "UNIT LOAD ACTIVE SUB DESCRIPTION +rtkit-daemon.service loaded inactive running RealtimeKit Scheduling Policy Service +setvtrgb.service loaded active exited Set console scheme +smartd.service masked failed dead smartd.service + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'." diff --git a/test/bin/failure/systemd-analyze b/test/bin/failure/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/failure/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/is_active/active/systemctl b/test/bin/is_active/active/systemctl new file mode 100755 index 0000000..141eec5 --- /dev/null +++ b/test/bin/is_active/active/systemctl @@ -0,0 +1,3 @@ +#! /bin/sh + +echo "active" diff --git a/test/bin/is_active/active/systemd-analyze b/test/bin/is_active/active/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/is_active/active/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/is_active/failed/systemctl b/test/bin/is_active/failed/systemctl new file mode 100755 index 0000000..63fece5 --- /dev/null +++ b/test/bin/is_active/failed/systemctl @@ -0,0 +1,3 @@ +#! /bin/sh + +echo "failed" diff --git a/test/bin/is_active/failed/systemd-analyze b/test/bin/is_active/failed/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/is_active/failed/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/is_active/inactive/systemctl b/test/bin/is_active/inactive/systemctl new file mode 100755 index 0000000..56c7d43 --- /dev/null +++ b/test/bin/is_active/inactive/systemctl @@ -0,0 +1,3 @@ +#! /bin/sh + +echo "inactive" diff --git a/test/bin/is_active/inactive/systemd-analyze b/test/bin/is_active/inactive/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/is_active/inactive/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/multiple_failure/systemctl b/test/bin/multiple_failure/systemctl new file mode 100755 index 0000000..7bc7adf --- /dev/null +++ b/test/bin/multiple_failure/systemctl @@ -0,0 +1,13 @@ +#! /bin/sh + +echo "UNIT LOAD ACTIVE SUB DESCRIPTION +rtkit-daemon.service loaded failed running RealtimeKit Scheduling Policy Service +setvtrgb.service loaded active exited Set console scheme +smartd.service masked failed dead smartd.service + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'." diff --git a/test/bin/multiple_failure/systemd-analyze b/test/bin/multiple_failure/systemd-analyze new file mode 100755 index 0000000..bef79f5 --- /dev/null +++ b/test/bin/multiple_failure/systemd-analyze @@ -0,0 +1,3 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 46.292s" diff --git a/test/bin/ok/systemctl b/test/bin/ok/systemctl new file mode 100755 index 0000000..5b22d7a --- /dev/null +++ b/test/bin/ok/systemctl @@ -0,0 +1,396 @@ +#! /bin/sh + +echo "UNIT LOAD ACTIVE SUB DESCRIPTION +mnt-nas.automount loaded active waiting Automount nnas +proc-sys-fs-binfmt_misc.automount loaded active waiting Arbitrary Executable File Formats File System Automount Point +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2did-nvme\x2deui.0025385771b00e60\x2dpart4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2did-nvme\x2dSamsung_SSD_960_EVO_250GB_S3ESNX0J700325J\x2dpart4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2dpartlabel-EFI\x5cx20System\x5cx20Partition.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2dpartuuid-1f489d33\x2db159\x2d43b0\x2dbb7b\x2d627b0f5257a6.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2dpartuuid-552a6e3d\x2d407e\x2d4766\x2d8108\x2d5d59b750e5c8.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2dpartuuid-bdf9e3c6\x2deac4\x2d46cc\x2d91cc\x2d82c4f67fce32.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2dpartuuid-edf6ea06\x2d605f\x2d4c5a\x2db6c1\x2d892fd24a6658.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2dpath-pci\x2d0000:3c:00.0\x2dnvme\x2d1\x2dpart4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2duuid-7B34B8C116E7DE4C.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-disk-by\x2duuid-823483A534839B35.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-disk-by\x2duuid-AE19\x2dC934.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-disk-by\x2duuid-d924ad1b\x2d56c6\x2d4871\x2d9573\x2d208c8978c558.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-loop0.device loaded active plugged /dev/loop0 +dev-loop1.device loaded active plugged /dev/loop1 +dev-loop2.device loaded active plugged /dev/loop2 +dev-loop3.device loaded active plugged /dev/loop3 +dev-loop4.device loaded active plugged /dev/loop4 +dev-nvme0n1.device loaded active plugged Samsung SSD 960 EVO 250GB +dev-nvme0n1p1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +dev-nvme0n1p2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +dev-nvme0n1p3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +dev-nvme0n1p4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +dev-rfkill.device loaded active plugged /dev/rfkill +dev-ttyprintk.device loaded active plugged /dev/ttyprintk +dev-ttyS0.device loaded active plugged /dev/ttyS0 +dev-ttyS1.device loaded active plugged /dev/ttyS1 +dev-ttyS10.device loaded active plugged /dev/ttyS10 +dev-ttyS11.device loaded active plugged /dev/ttyS11 +dev-ttyS12.device loaded active plugged /dev/ttyS12 +dev-ttyS13.device loaded active plugged /dev/ttyS13 +dev-ttyS14.device loaded active plugged /dev/ttyS14 +dev-ttyS15.device loaded active plugged /dev/ttyS15 +dev-ttyS16.device loaded active plugged /dev/ttyS16 +dev-ttyS17.device loaded active plugged /dev/ttyS17 +dev-ttyS18.device loaded active plugged /dev/ttyS18 +dev-ttyS19.device loaded active plugged /dev/ttyS19 +dev-ttyS2.device loaded active plugged /dev/ttyS2 +dev-ttyS20.device loaded active plugged /dev/ttyS20 +dev-ttyS21.device loaded active plugged /dev/ttyS21 +dev-ttyS22.device loaded active plugged /dev/ttyS22 +dev-ttyS23.device loaded active plugged /dev/ttyS23 +dev-ttyS24.device loaded active plugged /dev/ttyS24 +dev-ttyS25.device loaded active plugged /dev/ttyS25 +dev-ttyS26.device loaded active plugged /dev/ttyS26 +dev-ttyS27.device loaded active plugged /dev/ttyS27 +dev-ttyS28.device loaded active plugged /dev/ttyS28 +dev-ttyS29.device loaded active plugged /dev/ttyS29 +dev-ttyS3.device loaded active plugged /dev/ttyS3 +dev-ttyS30.device loaded active plugged /dev/ttyS30 +dev-ttyS31.device loaded active plugged /dev/ttyS31 +dev-ttyS4.device loaded active plugged /dev/ttyS4 +dev-ttyS5.device loaded active plugged /dev/ttyS5 +dev-ttyS6.device loaded active plugged /dev/ttyS6 +dev-ttyS7.device loaded active plugged /dev/ttyS7 +dev-ttyS8.device loaded active plugged /dev/ttyS8 +dev-ttyS9.device loaded active plugged /dev/ttyS9 +sys-devices-pci0000:00-0000:00:14.0-usb1-1\x2d8-1\x2d8:1.0-bluetooth-hci0.device loaded active plugged /sys/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/bluetooth/hci0 +sys-devices-pci0000:00-0000:00:1c.0-0000:01:00.0-0000:02:00.0-0000:03:00.0-domain0-0\x2d0-0\x2d1.device loaded active plugged /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/domain0/0-0/0-1 +sys-devices-pci0000:00-0000:00:1c.0-0000:01:00.0-0000:02:00.0-0000:03:00.0-domain0-0\x2d0.device loaded active plugged /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/domain0/0-0 +sys-devices-pci0000:00-0000:00:1c.0-0000:01:00.0-0000:02:00.0-0000:03:00.0-domain0.device loaded active plugged /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/domain0 +sys-devices-pci0000:00-0000:00:1c.5-0000:3a:00.0-net-wlp58s0.device loaded active plugged Wireless 8265 / 8275 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p1.device loaded active plugged Samsung SSD 960 EVO 250GB EFI\x20System\x20Partition +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p2.device loaded active plugged Samsung SSD 960 EVO 250GB 2 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p3.device loaded active plugged Samsung SSD 960 EVO 250GB 3 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1-nvme0n1p4.device loaded active plugged Samsung SSD 960 EVO 250GB 4 +sys-devices-pci0000:00-0000:00:1d.0-0000:3c:00.0-nvme-nvme0-nvme0n1.device loaded active plugged Samsung SSD 960 EVO 250GB +sys-devices-pci0000:00-0000:00:1f.3-sound-card0.device loaded active plugged Sunrise Point-LP HD Audio +sys-devices-pci0000:00-0000:00:1f.6-net-eno1.device loaded active plugged Ethernet Connection (4) I219-V +sys-devices-platform-serial8250-tty-ttyS0.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS0 +sys-devices-platform-serial8250-tty-ttyS1.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS1 +sys-devices-platform-serial8250-tty-ttyS10.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS10 +sys-devices-platform-serial8250-tty-ttyS11.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS11 +sys-devices-platform-serial8250-tty-ttyS12.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS12 +sys-devices-platform-serial8250-tty-ttyS13.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS13 +sys-devices-platform-serial8250-tty-ttyS14.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS14 +sys-devices-platform-serial8250-tty-ttyS15.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS15 +sys-devices-platform-serial8250-tty-ttyS16.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS16 +sys-devices-platform-serial8250-tty-ttyS17.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS17 +sys-devices-platform-serial8250-tty-ttyS18.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS18 +sys-devices-platform-serial8250-tty-ttyS19.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS19 +sys-devices-platform-serial8250-tty-ttyS2.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS2 +sys-devices-platform-serial8250-tty-ttyS20.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS20 +sys-devices-platform-serial8250-tty-ttyS21.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS21 +sys-devices-platform-serial8250-tty-ttyS22.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS22 +sys-devices-platform-serial8250-tty-ttyS23.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS23 +sys-devices-platform-serial8250-tty-ttyS24.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS24 +sys-devices-platform-serial8250-tty-ttyS25.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS25 +sys-devices-platform-serial8250-tty-ttyS26.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS26 +sys-devices-platform-serial8250-tty-ttyS27.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS27 +sys-devices-platform-serial8250-tty-ttyS28.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS28 +sys-devices-platform-serial8250-tty-ttyS29.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS29 +sys-devices-platform-serial8250-tty-ttyS3.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS3 +sys-devices-platform-serial8250-tty-ttyS30.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS30 +sys-devices-platform-serial8250-tty-ttyS31.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS31 +sys-devices-platform-serial8250-tty-ttyS4.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS4 +sys-devices-platform-serial8250-tty-ttyS5.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS5 +sys-devices-platform-serial8250-tty-ttyS6.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS6 +sys-devices-platform-serial8250-tty-ttyS7.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS7 +sys-devices-platform-serial8250-tty-ttyS8.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS8 +sys-devices-platform-serial8250-tty-ttyS9.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS9 +sys-devices-virtual-block-loop0.device loaded active plugged /sys/devices/virtual/block/loop0 +sys-devices-virtual-block-loop1.device loaded active plugged /sys/devices/virtual/block/loop1 +sys-devices-virtual-block-loop2.device loaded active plugged /sys/devices/virtual/block/loop2 +sys-devices-virtual-block-loop3.device loaded active plugged /sys/devices/virtual/block/loop3 +sys-devices-virtual-block-loop4.device loaded active plugged /sys/devices/virtual/block/loop4 +sys-devices-virtual-misc-rfkill.device loaded active plugged /sys/devices/virtual/misc/rfkill +sys-devices-virtual-tty-ttyprintk.device loaded active plugged /sys/devices/virtual/tty/ttyprintk +sys-module-configfs.device loaded active plugged /sys/module/configfs +sys-module-fuse.device loaded active plugged /sys/module/fuse +sys-subsystem-bluetooth-devices-hci0.device loaded active plugged /sys/subsystem/bluetooth/devices/hci0 +sys-subsystem-net-devices-eno1.device loaded active plugged Ethernet Connection (4) I219-V +sys-subsystem-net-devices-wlp58s0.device loaded active plugged Wireless 8265 / 8275 +-.mount loaded active mounted Root Mount +boot-efi.mount loaded active mounted /boot/efi +dev-hugepages.mount loaded active mounted Huge Pages File System +dev-mqueue.mount loaded active mounted POSIX Message Queue File System +mnt-ebook.mount loaded inactive dead Mount ebook +mnt-keepass.mount loaded inactive dead Mount keepass +mnt-lnas.mount loaded inactive dead Mount lnas +mnt-lnasdata.mount loaded inactive dead Mount lnasdata +mnt-nextcloudfirma.mount loaded inactive dead Automount /mnt/nextcloudfirma +mnt-nextcloudjf.mount loaded inactive dead Automount /mnt/nextcloudjf +mnt-nnas.mount loaded inactive dead Mount nnas +mnt-nnasdata.mount loaded inactive dead Mount nnasdata +mnt-wnas.mount loaded inactive dead Mount wnas +mnt-wnasdata.mount loaded inactive dead Mount wnasdata +proc-sys-fs-binfmt_misc.mount loaded inactive dead Arbitrary Executable File Formats File System +run-user-1000-gvfs.mount loaded active mounted /run/user/1000/gvfs +run-user-1000.mount loaded active mounted /run/user/1000 +run-user-121.mount loaded active mounted /run/user/121 +snap-core-5897.mount loaded active mounted Mount unit for core, revision 5897 +snap-core-6034.mount loaded active mounted Mount unit for core, revision 6034 +snap-core-6130.mount loaded active mounted Mount unit for core, revision 6130 +snap-filebot-16.mount loaded active mounted Mount unit for filebot, revision 16 +snap-filebot-9.mount loaded active mounted Mount unit for filebot, revision 9 +sys-fs-fuse-connections.mount loaded active mounted FUSE Control File System +sys-kernel-config.mount loaded active mounted Kernel Configuration File System +sys-kernel-debug.mount loaded active mounted Kernel Debug File System +tmp.mount not-found inactive dead tmp.mount +acpid.path loaded active running ACPI Events Check +apport-autoreport.path loaded active waiting Process error reports when automatic reporting is enabled (file watch) +cups.path loaded active running CUPS Scheduler +systemd-ask-password-console.path loaded inactive dead Dispatch Password Requests to Console Directory Watch +systemd-ask-password-plymouth.path loaded active waiting Forward Password Requests to Plymouth Directory Watch +systemd-ask-password-wall.path loaded active waiting Forward Password Requests to Wall Directory Watch +init.scope loaded active running System and Service Manager +session-2.scope loaded active running Session 2 of user jf +session-c1.scope loaded active running Session c1 of user gdm +accounts-daemon.service loaded active running Accounts Service +acpid.service loaded active running ACPI event daemon +alsa-restore.service loaded inactive dead Save/Restore Sound Card State +alsa-state.service loaded inactive dead Manage Sound Card State (restore and store) +anacron.service loaded inactive dead Run anacron jobs +apache2.service masked inactive dead apache2.service +apparmor.service masked inactive dead apparmor.service +apport-autoreport.service loaded inactive dead Process error reports when automatic reporting is enabled +apport.service loaded active exited LSB: automatic crash report generation +apt-daily-upgrade.service loaded inactive dead Daily apt upgrade and clean activities +apt-daily.service loaded inactive dead Daily apt download activities +auditd.service not-found inactive dead auditd.service +avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack +bind9.service loaded active running BIND Domain Name Server +blk-availability.service masked inactive dead blk-availability.service +bluetooth.service loaded active running Bluetooth service +bolt.service loaded active running Thunderbolt system service +certbot.service loaded inactive dead Certbot +cgroupfs-mount.service loaded active exited LSB: Set up cgroupfs mounts. +colord.service loaded active running Manage, Install and Generate Color Profiles +connman.service not-found inactive dead connman.service +console-screen.service not-found inactive dead console-screen.service +console-setup.service loaded active exited Set console font and keymap +containerd.service masked inactive dead containerd.service +cron.service loaded active running Regular background program processing daemon +cups.service loaded active running CUPS Scheduler +dbus.service loaded active running D-Bus System Message Bus +dfm-auto-jf.service loaded inactive dead dfm auto for user “jf” (dotfiles mangager auto update) +dfm-auto-root.service loaded inactive dead dfm auto for user “root” (dotfiles mangager auto update) +dns-clean.service loaded inactive dead Clean up any mess left by 0dns-up +docker.service masked inactive dead docker.service +ebtables.service masked inactive dead ebtables.service +emergency.service loaded inactive dead Emergency Shell +festival.service not-found inactive dead festival.service +fstrim.service loaded inactive dead Discard unused blocks +fwupd.service loaded active running Firmware update daemon +gdm.service loaded active running GNOME Display Manager +getty-static.service loaded inactive dead getty on tty2-tty6 if dbus and logind are not available +getty@tty1.service loaded inactive dead Getty on tty1 +gitup.service loaded inactive dead Run gitup (git-repo-updater) +google-fonts.service loaded inactive dead Google fonts update +gpu-manager.service loaded inactive dead Detect the available GPUs and deal with any system changes +grub-common.service loaded active exited LSB: Record successful boot for GRUB +hblock.service loaded inactive dead hBlock update (/etc/hosts) +irqbalance.service loaded active running irqbalance daemon +jfddns-update-script_nuc_dev-eno1_ipvboth.service loaded inactive dead jfddns-update-script.sh (nuc_dev-eno1_ipvboth) +kbd.service not-found inactive dead kbd.service +kerneloops.service loaded active running Tool to automatically collect and submit kernel crash signatures +keyboard-setup.service loaded active exited Set the console keyboard layout +kmod-static-nodes.service loaded active exited Create list of required static device nodes for the current kernel +libvirt-guests.service masked inactive dead libvirt-guests.service +libvirtd.service masked inactive dead libvirtd.service +lively-lights.service not-found inactive dead lively-lights.service +lvm2-lvmetad.service loaded active exited LSB: LVM2 metadata daemon +lvm2-lvmpolld.service loaded active exited LSB: LVM2 poll daemon +lvm2-monitor.service masked inactive dead lvm2-monitor.service +mariadb.service loaded active running MariaDB 10.1.38 database server +ModemManager.service loaded active running Modem Manager +mysqldump-all.service loaded inactive dead mysqldump-all +networkd-dispatcher.service loaded active running Dispatcher daemon for systemd-networkd +networking.service loaded active exited Raise network interfaces +NetworkManager-wait-online.service loaded active exited Network Manager Wait Online +NetworkManager.service loaded active running Network Manager +nginx.service loaded active running A high performance web server and a reverse proxy server +nmbd.service loaded active running Samba NMB Daemon +nsca-localhost.service loaded inactive dead NSCA localhost +oem-config.service not-found inactive dead oem-config.service +ondemand.service loaded inactive dead Set the CPU Frequency Scaling governor +openvpn.service masked inactive dead openvpn.service +packagekit.service loaded active running PackageKit Daemon +php7.2-fpm.service loaded active running The PHP 7.2 FastCGI Process Manager +phpsessionclean.service loaded inactive dead Clean php session files +plymouth-quit-wait.service loaded inactive dead Hold until boot process finishes up +plymouth-quit.service loaded inactive dead Terminate Plymouth Boot Screen +plymouth-read-write.service loaded inactive dead Tell Plymouth To Write Out Runtime Data +plymouth-start.service loaded inactive dead Show Plymouth Boot Screen +polkit.service loaded active running Authorization Manager +postfix.service masked inactive dead postfix.service +pppd-dns.service loaded inactive dead Restore /etc/resolv.conf if the system crashed before the ppp link was shut down +qemu-kvm.service loaded active exited QEMU KVM preparation - module, ksm, hugepages +rc-local.service loaded inactive dead /etc/rc.local Compatibility +rescue.service loaded inactive dead Rescue Shell +resolvconf.service not-found inactive dead resolvconf.service +rsync.service loaded inactive dead fast remote file copy program daemon +rsyslog.service loaded active running System Logging Service +rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy Service +setvtrgb.service loaded active exited Set console scheme +smartd.service masked inactive dead smartd.service +smbd.service loaded active running Samba SMB Daemon +snapd.autoimport.service masked inactive dead snapd.autoimport.service +snapd.core-fixup.service masked inactive dead snapd.core-fixup.service +snapd.seeded.service masked inactive dead snapd.seeded.service +snapd.service masked inactive dead snapd.service +speech-dispatcher.service loaded active exited LSB: Speech Dispatcher +ssh.service loaded active running OpenBSD Secure Shell server +systemd-ask-password-console.service loaded inactive dead Dispatch Password Requests to Console +systemd-ask-password-plymouth.service loaded inactive dead Forward Password Requests to Plymouth +systemd-ask-password-wall.service loaded inactive dead Forward Password Requests to Wall +systemd-binfmt.service loaded inactive dead Set Up Additional Binary Formats +systemd-fsck-root.service loaded inactive dead File System Check on Root Device +systemd-fsck@dev-disk-by\x2duuid-AE19\x2dC934.service loaded active exited File System Check on /dev/disk/by-uuid/AE19-C934 +systemd-fsckd.service loaded inactive dead File System Check Daemon to report status +systemd-hwdb-update.service loaded inactive dead Rebuild Hardware Database +systemd-initctl.service loaded inactive dead /dev/initctl Compatibility Daemon +systemd-journal-flush.service loaded active exited Flush Journal to Persistent Storage +systemd-journald.service loaded active running Journal Service +systemd-logind.service loaded active running Login Service +systemd-machine-id-commit.service loaded inactive dead Commit a transient machine-id on disk +systemd-modules-load.service loaded active exited Load Kernel Modules +systemd-networkd.service loaded inactive dead Network Service +systemd-quotacheck.service loaded inactive dead File System Quota Check +systemd-random-seed.service loaded active exited Load/Save Random Seed +systemd-remount-fs.service loaded active exited Remount Root and Kernel File Systems +systemd-resolved.service loaded active running Network Name Resolution +systemd-rfkill.service loaded inactive dead Load/Save RF Kill Switch Status +systemd-sysctl.service loaded active exited Apply Kernel Variables +systemd-sysusers.service not-found inactive dead systemd-sysusers.service +systemd-timesyncd.service loaded active running Network Time Synchronization +systemd-tmpfiles-clean.service loaded inactive dead Cleanup of Temporary Directories +systemd-tmpfiles-setup-dev.service loaded active exited Create Static Device Nodes in /dev +systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories +systemd-udev-trigger.service loaded active exited udev Coldplug all Devices +systemd-udevd.service loaded active running udev Kernel Device Manager +systemd-update-done.service not-found inactive dead systemd-update-done.service +systemd-update-utmp-runlevel.service loaded inactive dead Update UTMP about System Runlevel Changes +systemd-update-utmp.service loaded active exited Update UTMP about System Boot/Shutdown +systemd-user-sessions.service loaded active exited Permit User Sessions +systemd-vconsole-setup.service not-found inactive dead systemd-vconsole-setup.service +texlive-update.service loaded inactive dead TeXlive update +thermald.service loaded active running Thermal Daemon Service +tor.service loaded active exited Anonymizing overlay network for TCP (multi-instance-master) +tor@default.service loaded active running Anonymizing overlay network for TCP +udisks2.service loaded active running Disk Manager +ufw.service loaded active exited Uncomplicated firewall +unattended-upgrades-frequent.service loaded inactive dead unattended-upgrades +unattended-upgrades.service loaded active running Unattended Upgrades Shutdown +update-motd.service loaded inactive dead Run update-motd and generate /var/run/motd +upower.service loaded active running Daemon for power management +ureadahead-stop.service loaded inactive dead Stop ureadahead data collection +ureadahead.service loaded inactive dead Read required files in advance +user@1000.service loaded active running User Manager for UID 1000 +user@121.service loaded active running User Manager for UID 121 +uuidd.service loaded active running Daemon for generating UUIDs +vnstat.service loaded active exited LSB: lightweight network traffic monitor +vsftpd.service loaded active running vsftpd FTP server +whoopsie.service loaded active running crash report submission daemon +winbind.service not-found inactive dead winbind.service +wpa_supplicant.service loaded active running WPA supplicant +-.slice loaded active active Root Slice +system-getty.slice loaded active active system-getty.slice +system-systemd\x2dfsck.slice loaded active active system-systemd\x2dfsck.slice +system-tor.slice loaded active active system-tor.slice +system.slice loaded active active System Slice +user-1000.slice loaded active active User Slice of jf +user-121.slice loaded active active User Slice of gdm +user.slice loaded active active User and Session Slice +acpid.socket loaded active running ACPID Listen Socket +avahi-daemon.socket loaded active running Avahi mDNS/DNS-SD Stack Activation Socket +cups.socket loaded active running CUPS Scheduler +dbus.socket loaded active running D-Bus System Message Bus Socket +dm-event.socket masked inactive dead dm-event.socket +docker.socket not-found inactive dead docker.socket +lvm2-lvmetad.socket masked inactive dead lvm2-lvmetad.socket +lvm2-lvmpolld.socket masked inactive dead lvm2-lvmpolld.socket +snapd.socket masked inactive dead snapd.socket +syslog.socket loaded active running Syslog Socket +systemd-fsckd.socket loaded active listening fsck to fsckd communication Socket +systemd-initctl.socket loaded active listening /dev/initctl Compatibility Named Pipe +systemd-journald-audit.socket loaded active running Journal Audit Socket +systemd-journald-dev-log.socket loaded active running Journal Socket (/dev/log) +systemd-journald.socket loaded active running Journal Socket +systemd-rfkill.socket loaded active listening Load/Save RF Kill Switch Status /dev/rfkill Watch +systemd-udevd-control.socket loaded active running udev Control Socket +systemd-udevd-kernel.socket loaded active running udev Kernel Socket +uuidd.socket loaded active running UUID daemon activation socket +virtlockd.socket masked inactive dead virtlockd.socket +virtlogd.socket masked inactive dead virtlogd.socket +swapfile.swap loaded active active /swapfile +all.target not-found inactive dead all.target +basic.target loaded active active Basic System +bluetooth.target loaded active active Bluetooth +cryptsetup.target loaded active active Local Encrypted Volumes +emergency.target loaded inactive dead Emergency Mode +getty-pre.target loaded inactive dead Login Prompts (Pre) +getty.target loaded active active Login Prompts +graphical.target loaded active active Graphical Interface +local-fs-pre.target loaded active active Local File Systems (Pre) +local-fs.target loaded active active Local File Systems +multi-user.target loaded active active Multi-User System +network-online.target loaded active active Network is Online +network-pre.target loaded inactive dead Network (Pre) +network.target loaded active active Network +nss-lookup.target loaded active active Host and Network Name Lookups +nss-user-lookup.target loaded active active User and Group Name Lookups +paths.target loaded active active Paths +remote-fs-pre.target loaded inactive dead Remote File Systems (Pre) +remote-fs.target loaded active active Remote File Systems +rescue.target loaded inactive dead Rescue Mode +shutdown.target loaded inactive dead Shutdown +slices.target loaded active active Slices +sockets.target loaded active active Sockets +sound.target loaded active active Sound Card +swap.target loaded active active Swap +sysinit.target loaded active active System Initialization +syslog.target not-found inactive dead syslog.target +time-sync.target loaded active active System Time Synchronized +timers.target loaded active active Timers +umount.target loaded inactive dead Unmount All Filesystems +anacron.timer loaded active waiting Trigger anacron every hour +apt-daily-upgrade.timer loaded active waiting Daily apt upgrade and clean activities +apt-daily.timer loaded active waiting Daily apt activities +certbot.timer loaded active waiting Run certbot twice daily +fstrim.timer loaded active waiting Discard unused blocks once a week +motd-news.timer masked inactive dead motd-news.timer +mysqldump-all.timer loaded active waiting mysqldump-all +nsca-localhost.timer loaded active waiting NSCA localhost +nsupdate-nuc.jf-dyndns.cf.timer not-found inactive dead nsupdate-nuc.jf-dyndns.cf.timer +phpsessionclean.timer loaded active waiting Clean PHP session files every 30 mins +snapd.refresh.timer not-found inactive dead snapd.refresh.timer +snapd.snap-repair.timer masked inactive dead snapd.snap-repair.timer +systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories +unattended-upgrades-frequent.timer loaded active waiting unattended-upgrades +update-motd.timer loaded active waiting Run update-motd and generate /var/run/motd +ureadahead-stop.timer loaded active elapsed Stop ureadahead data collection 45s after completed startup + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'." diff --git a/test/bin/ok/systemd-analyze b/test/bin/ok/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/ok/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/regexp_excludes/systemctl b/test/bin/regexp_excludes/systemctl new file mode 100755 index 0000000..6da6d9d --- /dev/null +++ b/test/bin/regexp_excludes/systemctl @@ -0,0 +1,15 @@ +#! /bin/sh + +echo "UNIT LOAD ACTIVE SUB DESCRIPTION +rtkit-daemon.service loaded inactive running RealtimeKit Scheduling Policy Service +setvtrgb.service loaded active exited Set console scheme +user@123.service loaded failed failed User Manager for UID 123 +user@234.service loaded failed failed User Manager for UID 234 +user@345.service loaded failed failed User Manager for UID 345 + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'." diff --git a/test/bin/regexp_excludes/systemd-analyze b/test/bin/regexp_excludes/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/regexp_excludes/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/bin/version_246/systemctl b/test/bin/version_246/systemctl new file mode 100755 index 0000000..7a69798 --- /dev/null +++ b/test/bin/version_246/systemctl @@ -0,0 +1,349 @@ +#! /bin/sh + +echo " UNIT LOAD ACTIVE SUB DESCRIPTION + dev-block-254:0.device loaded active plugged /dev/block/254:0 + dev-block-254:1.device loaded active plugged /dev/block/254:1 + dev-disk-by\x2did-ata\x2dHITACHI_HTS723232A7A364_E3834563K5NVSN.device loaded active plugged HITACHI_HTS723232A7A364 + dev-disk-by\x2did-ata\x2dHITACHI_HTS723232A7A364_E3834563K5NVSN\x2dpart1.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2did-ata\x2dHITACHI_HTS723232A7A364_E3834563K5NVSN\x2dpart2.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-disk-by\x2did-ata\x2dHITACHI_HTS723232A7A364_E3834563K5NVSN\x2dpart4.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-disk-by\x2did-ata\x2dTOSHIBA_MQ01ABD100_Z6M7P2Q0T.device loaded active plugged TOSHIBA_MQ01ABD100 + dev-disk-by\x2did-ata\x2dTOSHIBA_MQ01ABD100_Z6M7P2Q0T\x2dpart1.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-disk-by\x2did-dm\x2dname\x2dcleartera.device loaded active plugged /dev/disk/by-id/dm-name-cleartera + dev-disk-by\x2did-dm\x2dname\x2dcleartext.device loaded active plugged /dev/disk/by-id/dm-name-cleartext + dev-disk-by\x2did-dm\x2dname\x2dlvm\x2droot.device loaded active plugged /dev/disk/by-id/dm-name-lvm-root + dev-disk-by\x2did-dm\x2dname\x2dlvm\x2dswap.device loaded active plugged /dev/disk/by-id/dm-name-lvm-swap + dev-disk-by\x2did-dm\x2dname\x2dteradisk\x2darchive.device loaded active plugged /dev/disk/by-id/dm-name-teradisk-archive + dev-disk-by\x2did-dm\x2dname\x2dteradisk\x2droot\x2d\x2dmirror.device loaded active plugged /dev/disk/by-id/dm-name-teradisk-root--mirror + dev-disk-by\x2did-dm\x2duuid\x2dCRYPT\x2dLUKS1\x2dfc78a5931403454294b5a12bd668726d\x2dcleartext.device loaded active plugged /dev/disk/by-id/dm-uuid-CRYPT-LUKS1-fc78a5931403454294b5a12bd668726d-cleartext + dev-disk-by\x2did-dm\x2duuid\x2dCRYPT\x2dLUKS2\x2d90a57b32d83d45ada696d054f442cc4b\x2dcleartera.device loaded active plugged /dev/disk/by-id/dm-uuid-CRYPT-LUKS2-90a57b32d83d45ada696d054f442cc4b-cleartera + dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2d8n8ccXWKi0IXDGaz6FWiJegeVk4056Bidkjto74u7XIcfmwSqykRL6ZDqgWbLlid.device loaded active plugged /dev/disk/by-id/dm-uuid-LVM-8n8ccXWKi0IXDGaz6FWiJegeVk4056Bidkjto74u7XIcfmwSqykRL6ZDqgWbLlid + dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2d8n8ccXWKi0IXDGaz6FWiJegeVk4056BiuK6cAvrVBMHRbOxIuoMMHpNQzaNNt5aH.device loaded active plugged /dev/disk/by-id/dm-uuid-LVM-8n8ccXWKi0IXDGaz6FWiJegeVk4056BiuK6cAvrVBMHRbOxIuoMMHpNQzaNNt5aH + dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dOcI4YLGWmw1IljsHTC2U2SVsay4GYYfWAajqhctTQol4FzKCyPdkRJvsAxJaZgmd.device loaded active plugged /dev/disk/by-id/dm-uuid-LVM-OcI4YLGWmw1IljsHTC2U2SVsay4GYYfWAajqhctTQol4FzKCyPdkRJvsAxJaZgmd + dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dOcI4YLGWmw1IljsHTC2U2SVsay4GYYfWkszJfX4DjIxOLR9TOPZtOaukQzW2zZ2f.device loaded active plugged /dev/disk/by-id/dm-uuid-LVM-OcI4YLGWmw1IljsHTC2U2SVsay4GYYfWkszJfX4DjIxOLR9TOPZtOaukQzW2zZ2f + dev-disk-by\x2did-lvm\x2dpv\x2duuid\x2dcy3zIM\x2dqNKi\x2dEmnR\x2dTLV6\x2dFPsB\x2dTlOF\x2dLJt6g5.device loaded active plugged /dev/disk/by-id/lvm-pv-uuid-cy3zIM-qNKi-EmnR-TLV6-FPsB-TlOF-LJt6g5 + dev-disk-by\x2did-lvm\x2dpv\x2duuid\x2dkZk45h\x2djp6P\x2dYI7W\x2dyQjp\x2dzlOa\x2dYusA\x2dA9349g.device loaded active plugged /dev/disk/by-id/lvm-pv-uuid-kZk45h-jp6P-YI7W-yQjp-zlOa-YusA-A9349g + dev-disk-by\x2did-wwn\x2d0x50000397724881e9.device loaded active plugged TOSHIBA_MQ01ABD100 + dev-disk-by\x2did-wwn\x2d0x50000397724881e9\x2dpart1.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-disk-by\x2did-wwn\x2d0x5000cca61decdaaf.device loaded active plugged HITACHI_HTS723232A7A364 + dev-disk-by\x2did-wwn\x2d0x5000cca61decdaaf\x2dpart1.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2did-wwn\x2d0x5000cca61decdaaf\x2dpart2.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-disk-by\x2did-wwn\x2d0x5000cca61decdaaf\x2dpart4.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-disk-by\x2dlabel-R\xc3\xa9serv\xc3\xa9\x5cx20au\x5cx20syst\xc3\xa8me.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2dpartuuid-50afadcc\x2d6ce4\x2d4b4f\x2da592\x2dc5a2b240e579.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-disk-by\x2dpartuuid-94f13043\x2d01.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2dpartuuid-94f13043\x2d02.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-disk-by\x2dpartuuid-94f13043\x2d04.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1.0.device loaded active plugged HITACHI_HTS723232A7A364 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1.0\x2dpart1.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1.0\x2dpart2.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1.0\x2dpart4.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1.device loaded active plugged HITACHI_HTS723232A7A364 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1\x2dpart1.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1\x2dpart2.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d1\x2dpart4.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d2.0.device loaded active plugged TOSHIBA_MQ01ABD100 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d2.0\x2dpart1.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d2.device loaded active plugged TOSHIBA_MQ01ABD100 + dev-disk-by\x2dpath-pci\x2d0000:00:1f.2\x2data\x2d2\x2dpart1.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-disk-by\x2duuid-1881f70f\x2dfbf5\x2d4044\x2dbfe8\x2dd7a6300c6818.device loaded active plugged /dev/disk/by-uuid/1881f70f-fbf5-4044-bfe8-d7a6300c6818 + dev-disk-by\x2duuid-50A020EFA020DCEA.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-disk-by\x2duuid-680b789b\x2d3bd6\x2d4b1c\x2d89e9\x2d660035df92dc.device loaded active plugged /dev/disk/by-uuid/680b789b-3bd6-4b1c-89e9-660035df92dc + dev-disk-by\x2duuid-882C22A02C228970.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-disk-by\x2duuid-90a57b32\x2dd83d\x2d45ad\x2da696\x2dd054f442cc4b.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-disk-by\x2duuid-d996bd3a\x2dc6fe\x2d4455\x2d9726\x2d2171e0ad8c6c.device loaded active plugged /dev/disk/by-uuid/d996bd3a-c6fe-4455-9726-2171e0ad8c6c + dev-disk-by\x2duuid-fc78a593\x2d1403\x2d4542\x2d94b5\x2da12bd668726d.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-dm\x2d0.device loaded active plugged /dev/dm-0 + dev-dm\x2d1.device loaded active plugged /dev/dm-1 + dev-dm\x2d2.device loaded active plugged /dev/dm-2 + dev-dm\x2d3.device loaded active plugged /dev/dm-3 + dev-dm\x2d4.device loaded active plugged /dev/dm-4 + dev-dm\x2d5.device loaded active plugged /dev/dm-5 + dev-input-mice.device loaded active plugged /dev/input/mice + dev-lvm-root.device loaded active plugged /dev/lvm/root + dev-lvm-swap.device loaded active plugged /dev/lvm/swap + dev-mapper-cleartera.device loaded active plugged /dev/mapper/cleartera + dev-mapper-cleartext.device loaded active plugged /dev/mapper/cleartext + dev-mapper-lvm\x2droot.device loaded active plugged /dev/mapper/lvm-root + dev-mapper-lvm\x2dswap.device loaded active plugged /dev/mapper/lvm-swap + dev-mapper-teradisk\x2darchive.device loaded active plugged /dev/mapper/teradisk-archive + dev-mapper-teradisk\x2droot\x2d\x2dmirror.device loaded active plugged /dev/mapper/teradisk-root--mirror + dev-net-tun.device loaded active plugged /dev/net/tun + dev-ram0.device loaded active plugged /dev/ram0 + dev-ram1.device loaded active plugged /dev/ram1 + dev-ram10.device loaded active plugged /dev/ram10 + dev-ram11.device loaded active plugged /dev/ram11 + dev-ram12.device loaded active plugged /dev/ram12 + dev-ram13.device loaded active plugged /dev/ram13 + dev-ram14.device loaded active plugged /dev/ram14 + dev-ram15.device loaded active plugged /dev/ram15 + dev-ram2.device loaded active plugged /dev/ram2 + dev-ram3.device loaded active plugged /dev/ram3 + dev-ram4.device loaded active plugged /dev/ram4 + dev-ram5.device loaded active plugged /dev/ram5 + dev-ram6.device loaded active plugged /dev/ram6 + dev-ram7.device loaded active plugged /dev/ram7 + dev-ram8.device loaded active plugged /dev/ram8 + dev-ram9.device loaded active plugged /dev/ram9 + dev-rfkill.device loaded active plugged /dev/rfkill + dev-sda.device loaded active plugged TOSHIBA_MQ01ABD100 + dev-sda1.device loaded active plugged TOSHIBA_MQ01ABD100 1 + dev-sdb.device loaded active plugged HITACHI_HTS723232A7A364 + dev-sdb1.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + dev-sdb2.device loaded active plugged HITACHI_HTS723232A7A364 2 + dev-sdb4.device loaded active plugged HITACHI_HTS723232A7A364 4 + dev-teradisk-archive.device loaded active plugged /dev/teradisk/archive + dev-teradisk-root\x2dmirror.device loaded active plugged /dev/teradisk/root-mirror + dev-ttyS0.device loaded active plugged /dev/ttyS0 + dev-ttyS1.device loaded active plugged /dev/ttyS1 + dev-ttyS2.device loaded active plugged /dev/ttyS2 + dev-ttyS3.device loaded active plugged /dev/ttyS3 + dev-zram0.device loaded active plugged /dev/zram0 + sys-devices-pci0000:00-0000:00:02.0-backlight-acpi_video0.device loaded active plugged /sys/devices/pci0000:00/0000:00:02.0/backlight/acpi_video0 + sys-devices-pci0000:00-0000:00:02.0-drm-card0-card0\x2dLVDS\x2d1-intel_backlight.device loaded active plugged /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/intel_backlight + sys-devices-pci0000:00-0000:00:19.0-net-enp0s25.device loaded active plugged 82579LM Gigabit Network Connection (Lewisville) (ThinkPad T520) + sys-devices-pci0000:00-0000:00:1b.0-sound-card0.device loaded active plugged 6 Series/C200 Series Chipset Family High Definition Audio Controller + sys-devices-pci0000:00-0000:00:1c.1-0000:03:00.0-net-wlp3s0.device loaded active plugged Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 (802.11a/b/g/n)) + sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sdb-sdb1.device loaded active plugged HITACHI_HTS723232A7A364 Réservé_au_système + sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sdb-sdb2.device loaded active plugged HITACHI_HTS723232A7A364 2 + sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sdb-sdb4.device loaded active plugged HITACHI_HTS723232A7A364 4 + sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sdb.device loaded active plugged HITACHI_HTS723232A7A364 + sys-devices-pci0000:00-0000:00:1f.2-ata2-host1-target1:0:0-1:0:0:0-block-sda-sda1.device loaded active plugged TOSHIBA_MQ01ABD100 1 + sys-devices-pci0000:00-0000:00:1f.2-ata2-host1-target1:0:0-1:0:0:0-block-sda.device loaded active plugged TOSHIBA_MQ01ABD100 + sys-devices-platform-serial8250-tty-ttyS0.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS0 + sys-devices-platform-serial8250-tty-ttyS1.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS1 + sys-devices-platform-serial8250-tty-ttyS2.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS2 + sys-devices-platform-serial8250-tty-ttyS3.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS3 + sys-devices-virtual-block-dm\x2d0.device loaded active plugged /sys/devices/virtual/block/dm-0 + sys-devices-virtual-block-dm\x2d1.device loaded active plugged /sys/devices/virtual/block/dm-1 + sys-devices-virtual-block-dm\x2d2.device loaded active plugged /sys/devices/virtual/block/dm-2 + sys-devices-virtual-block-dm\x2d3.device loaded active plugged /sys/devices/virtual/block/dm-3 + sys-devices-virtual-block-dm\x2d4.device loaded active plugged /sys/devices/virtual/block/dm-4 + sys-devices-virtual-block-dm\x2d5.device loaded active plugged /sys/devices/virtual/block/dm-5 + sys-devices-virtual-block-ram0.device loaded active plugged /sys/devices/virtual/block/ram0 + sys-devices-virtual-block-ram1.device loaded active plugged /sys/devices/virtual/block/ram1 + sys-devices-virtual-block-ram10.device loaded active plugged /sys/devices/virtual/block/ram10 + sys-devices-virtual-block-ram11.device loaded active plugged /sys/devices/virtual/block/ram11 + sys-devices-virtual-block-ram12.device loaded active plugged /sys/devices/virtual/block/ram12 + sys-devices-virtual-block-ram13.device loaded active plugged /sys/devices/virtual/block/ram13 + sys-devices-virtual-block-ram14.device loaded active plugged /sys/devices/virtual/block/ram14 + sys-devices-virtual-block-ram15.device loaded active plugged /sys/devices/virtual/block/ram15 + sys-devices-virtual-block-ram2.device loaded active plugged /sys/devices/virtual/block/ram2 + sys-devices-virtual-block-ram3.device loaded active plugged /sys/devices/virtual/block/ram3 + sys-devices-virtual-block-ram4.device loaded active plugged /sys/devices/virtual/block/ram4 + sys-devices-virtual-block-ram5.device loaded active plugged /sys/devices/virtual/block/ram5 + sys-devices-virtual-block-ram6.device loaded active plugged /sys/devices/virtual/block/ram6 + sys-devices-virtual-block-ram7.device loaded active plugged /sys/devices/virtual/block/ram7 + sys-devices-virtual-block-ram8.device loaded active plugged /sys/devices/virtual/block/ram8 + sys-devices-virtual-block-ram9.device loaded active plugged /sys/devices/virtual/block/ram9 + sys-devices-virtual-block-zram0.device loaded active plugged /sys/devices/virtual/block/zram0 + sys-devices-virtual-input-mice.device loaded active plugged /sys/devices/virtual/input/mice + sys-devices-virtual-misc-rfkill.device loaded active plugged /sys/devices/virtual/misc/rfkill + sys-devices-virtual-misc-tun.device loaded active plugged /sys/devices/virtual/misc/tun + sys-module-fuse.device loaded active plugged /sys/module/fuse + sys-module-tun.device loaded active plugged /sys/module/tun + sys-subsystem-net-devices-enp0s25.device loaded active plugged 82579LM Gigabit Network Connection (Lewisville) (ThinkPad T520) + sys-subsystem-net-devices-wlp3s0.device loaded active plugged Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 (802.11a/b/g/n)) + -.mount loaded active mounted Root Mount + archive.mount loaded active mounted /archive + boot.mount loaded active mounted /boot + dev-hugepages.mount loaded active mounted Huge Pages File System + dev-mqueue.mount loaded active mounted POSIX Message Queue File System + nix-store.mount loaded active mounted /nix/store + run-keys.mount loaded active mounted /run/keys + run-user-1000-gvfs.mount loaded active mounted /run/user/1000/gvfs + run-user-1000.mount loaded active mounted /run/user/1000 + run-wrappers.mount loaded active mounted /run/wrappers + sys-fs-fuse-connections.mount loaded active mounted FUSE Control File System + sys-kernel-config.mount loaded inactive dead Kernel Configuration File System + sys-kernel-debug-tracing.mount loaded active mounted /sys/kernel/debug/tracing + sys-kernel-debug.mount loaded active mounted Kernel Debug File System +● tmp.mount not-found inactive dead tmp.mount + systemd-ask-password-console.path loaded inactive dead Dispatch Password Requests to Console Directory Watch + systemd-ask-password-plymouth.path loaded active running Forward Password Requests to Plymouth Directory Watch + systemd-ask-password-wall.path loaded active waiting Forward Password Requests to Wall Directory Watch + init.scope loaded active running System and Service Manager + session-2.scope loaded active running Session 2 of user symphorien + accounts-daemon.service loaded active running Accounts Service +● acpid.service not-found inactive dead acpid.service + alsa-store.service loaded active exited Store Sound Card State + audit.service loaded active exited Kernel Auditing +● auditd.service not-found inactive dead auditd.service + batterycheck.service loaded inactive dead Hibernate on low battery + borgbackup-job-nlaptop.service loaded inactive dead BorgBackup job nlaptop + btrbk-home.service loaded inactive dead Takes BTRFS snapshots and maintains retention policies. + btrbk-remote.service loaded inactive dead Takes BTRFS snapshots and maintains retention policies. + btrfs-autobalance.service loaded inactive dead keep some unallocated space on root btrfs +● btrfs-defrag.service not-found inactive dead btrfs-defrag.service +● btrfs-scrub-.service not-found inactive dead btrfs-scrub-.service + cups.service loaded active running CUPS Scheduler + dbus.service loaded active running D-Bus System Message Bus + display-manager.service loaded active running X11 Server + earlyoom.service loaded active running Early OOM Daemon for Linux + emergency.service loaded inactive dead Emergency Shell +● fcoe.service not-found inactive dead fcoe.service + firewall.service loaded active exited Firewall + getty@tty1.service loaded active running Getty on tty1 + getty@tty7.service loaded inactive dead Getty on tty7 + gpm.service loaded active running Console Mouse Daemon + hdapsd@sda.service loaded active running hdapsd hard drive active protection system daemon - sda + hdapsd@sdb.service loaded active running hdapsd hard drive active protection system daemon - sdb +● iscsi.service not-found inactive dead iscsi.service + kmod-static-nodes.service loaded active exited Create list of static device nodes for the current kernel + lvm2-activation-early.service loaded inactive dead LVM direct activation of logical volumes + lvm2-activation-net.service loaded inactive dead LVM direct activation of logical volumes + lvm2-activation.service loaded inactive dead LVM direct activation of logical volumes + lvm2-pvscan@254:0.service loaded active exited LVM event activation on device 254:0 + lvm2-pvscan@254:1.service loaded active exited LVM event activation on device 254:1 +● modprobe@drm.service not-found inactive dead modprobe@drm.service + network-local-commands.service loaded active exited Extra networking commands. + network-really-online.service loaded inactive dead wait network to be really online + network-setup.service loaded active exited Networking Setup + NetworkManager-dispatcher.service loaded inactive dead Network Manager Script Dispatcher Service + NetworkManager-wait-online.service loaded active exited Network Manager Wait Online + NetworkManager.service loaded active running Network Manager + nix-daemon.service loaded active running Nix Daemon +● nixos-upgrade.service not-found inactive dead nixos-upgrade.service +● nm-wait-online.service loaded failed failed wait for network manager to connect to something +● openvswitch.service not-found inactive dead openvswitch.service + plymouth-quit-wait.service loaded inactive dead Hold until boot process finishes up + plymouth-quit.service loaded inactive dead Terminate Plymouth Boot Screen + plymouth-read-write.service loaded inactive dead Tell Plymouth To Write Out Runtime Data + plymouth-start.service loaded inactive dead Show Plymouth Boot Screen + polkit.service loaded active running Authorization Manager + post-resume.service loaded inactive dead Post-Resume Actions + powertop.service loaded active exited Powertop tunings + pre-sleep.service loaded inactive dead Pre-Sleep Actions +● rbdmap.service not-found inactive dead rbdmap.service +● rc-local.service not-found inactive dead rc-local.service + rescue.service loaded inactive dead Rescue Shell + resolvconf.service loaded active exited resolvconf update + rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy Service + save-hwclock.service loaded inactive dead Save Hardware Clock + sshd.service loaded active running SSH Daemon +● sssd.service not-found inactive dead sssd.service +● syslog.service not-found inactive dead syslog.service + systemd-ask-password-console.service loaded inactive dead Dispatch Password Requests to Console + systemd-ask-password-plymouth.service loaded active running Forward Password Requests to Plymouth + systemd-ask-password-wall.service loaded inactive dead Forward Password Requests to Wall + systemd-backlight@backlight:acpi_video0.service loaded active exited Load/Save Screen Backlight Brightness of backlight:acpi_video0 + systemd-backlight@backlight:intel_backlight.service loaded active exited Load/Save Screen Backlight Brightness of backlight:intel_backlight + systemd-fsck-root.service loaded inactive dead File System Check on Root Device + systemd-fsck@dev-disk-by\x2duuid-680b789b\x2d3bd6\x2d4b1c\x2d89e9\x2d660035df92dc.service loaded active exited File System Check on /dev/disk/by-uuid/680b789b-3bd6-4b1c-89e9-660035df92dc + systemd-hibernate.service loaded inactive dead Hibernate +● systemd-hwdb-update.service not-found inactive dead systemd-hwdb-update.service + systemd-hybrid-sleep.service loaded inactive dead Hybrid Suspend+Hibernate + systemd-journal-catalog-update.service loaded inactive dead Rebuild Journal Catalog + systemd-journal-flush.service loaded active exited Flush Journal to Persistent Storage + systemd-journald.service loaded active running Journal Service + systemd-logind.service loaded active running User Login Management + systemd-machined.service loaded inactive dead Virtual Machine and Container Registration Service + systemd-modules-load.service loaded active exited Load Kernel Modules +● systemd-quotacheck.service not-found inactive dead systemd-quotacheck.service + systemd-random-seed.service loaded active exited Load/Save Random Seed + systemd-remount-fs.service loaded active exited Remount Root and Kernel File Systems + systemd-suspend.service loaded inactive dead Suspend + systemd-sysctl.service loaded active exited Apply Kernel Variables +● systemd-sysusers.service not-found inactive dead systemd-sysusers.service + systemd-timesyncd.service loaded active running Network Time Synchronization + systemd-tmpfiles-clean.service loaded inactive dead Cleanup of Temporary Directories + systemd-tmpfiles-setup-dev.service loaded active exited Create Static Device Nodes in /dev + systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories + systemd-udev-settle.service loaded active exited Wait for udev To Complete Device Initialization + systemd-udev-trigger.service loaded active exited Coldplug All udev Devices + systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files + systemd-update-done.service loaded inactive dead Update is Completed + systemd-update-utmp.service loaded active exited Update UTMP about System Boot/Shutdown + systemd-user-sessions.service loaded active exited Permit User Sessions + systemd-vconsole-setup.service loaded inactive dead Setup Virtual Console + thinkfan.service loaded active running Thinkfan + tlp-sleep.service loaded inactive dead TLP suspend/resume + tlp.service loaded active exited TLP system startup/shutdown + udisks2.service loaded active running Disk Manager +● update-locatedb.service not-found inactive dead update-locatedb.service + upower.service loaded active running Daemon for power management + user-runtime-dir@1000.service loaded active exited User Runtime Directory /run/user/1000 + user@1000.service loaded active running User Manager for UID 1000 + wpa_supplicant.service loaded active running WPA supplicant + zram-init-zram0.service loaded active exited Init swap on zram-based device zram0 + zram-reloader.service loaded active exited Reload zram kernel module when number of devices changes + -.slice loaded active active Root Slice + machine.slice loaded inactive dead Virtual Machine and Container Slice + system-getty.slice loaded active active system-getty.slice + system-hdapsd.slice loaded active active system-hdapsd.slice + system-lvm2\x2dpvscan.slice loaded active active system-lvm2\x2dpvscan.slice + system-systemd\x2dbacklight.slice loaded active active system-systemd\x2dbacklight.slice + system-systemd\x2dcoredump.slice loaded active active system-systemd\x2dcoredump.slice + system-systemd\x2dfsck.slice loaded active active system-systemd\x2dfsck.slice + system.slice loaded active active System Slice + user-1000.slice loaded active active user-1000.slice + user-78.slice loaded active active user-78.slice + user.slice loaded active active User and Session Slice + cups.socket loaded active running CUPS Scheduler + dbus.socket loaded active running D-Bus System Message Bus Socket + nix-daemon.socket loaded active running Nix Daemon Socket + syslog.socket loaded inactive dead Syslog Socket + systemd-coredump.socket loaded active listening Process Core Dump Socket + systemd-journald-audit.socket loaded active running Journal Audit Socket + systemd-journald-dev-log.socket loaded active running Journal Socket (/dev/log) + systemd-journald.socket loaded active running Journal Socket +● systemd-rfkill.socket masked inactive dead systemd-rfkill.socket + systemd-udevd-control.socket loaded active running udev Control Socket + systemd-udevd-kernel.socket loaded active running udev Kernel Socket + dev-zram0.swap loaded active active /dev/zram0 + basic.target loaded active active Basic System +● blockdev@dev-disk-by\x2duuid-1881f70f\x2dfbf5\x2d4044\x2dbfe8\x2dd7a6300c6818.target not-found inactive dead blockdev@dev-disk-by\x2duuid-1881f70f\x2dfbf5\x2d4044\x2dbfe8\x2dd7a6300c6818.target +● blockdev@dev-disk-by\x2duuid-680b789b\x2d3bd6\x2d4b1c\x2d89e9\x2d660035df92dc.target not-found inactive dead blockdev@dev-disk-by\x2duuid-680b789b\x2d3bd6\x2d4b1c\x2d89e9\x2d660035df92dc.target +● blockdev@dev-disk-by\x2duuid-d996bd3a\x2dc6fe\x2d4455\x2d9726\x2d2171e0ad8c6c.target not-found inactive dead blockdev@dev-disk-by\x2duuid-d996bd3a\x2dc6fe\x2d4455\x2d9726\x2d2171e0ad8c6c.target +● blockdev@dev-dm\x2d3.target not-found inactive dead blockdev@dev-dm\x2d3.target +● blockdev@dev-mapper-lvm\x2dswap.target not-found inactive dead blockdev@dev-mapper-lvm\x2dswap.target +● blockdev@dev-mapper-teradisk\x2darchive.target not-found inactive dead blockdev@dev-mapper-teradisk\x2darchive.target +● blockdev@dev-zram0.target not-found inactive dead blockdev@dev-zram0.target + cryptsetup.target loaded active active Local Encrypted Volumes + emergency.target loaded inactive dead Emergency Mode + getty-pre.target loaded inactive dead Login Prompts (Pre) + getty.target loaded active active Login Prompts + graphical.target loaded active active Graphical Interface + hibernate.target loaded inactive dead Hibernate + hybrid-sleep.target loaded inactive dead Hybrid Suspend+Hibernate +● initrd-switch-root.target not-found inactive dead initrd-switch-root.target + local-fs-pre.target loaded active active Local File Systems (Pre) + local-fs.target loaded active active Local File Systems + machines.target loaded active active Containers + multi-user.target loaded active active Multi-User System + network-interfaces.target loaded active active All Network Interfaces (deprecated) + network-online.target loaded active active Network is Online + network-pre.target loaded active active Network (Pre) + network.target loaded active active Network + nss-lookup.target loaded active active Host and Network Name Lookups + nss-user-lookup.target loaded active active User and Group Name Lookups + paths.target loaded active active Paths + post-resume.target loaded inactive dead Post-Resume Actions + remote-fs-pre.target loaded inactive dead Remote File Systems (Pre) + remote-fs.target loaded active active Remote File Systems + rescue.target loaded inactive dead Rescue Mode + shutdown.target loaded inactive dead Shutdown + sleep.target loaded inactive dead Sleep + slices.target loaded active active Slices + sockets.target loaded active active Sockets + sound.target loaded active active Sound Card + suspend.target loaded inactive dead Suspend + swap.target loaded active active Swap + sysinit.target loaded active active System Initialization +● time-set.target not-found inactive dead time-set.target + time-sync.target loaded active active System Time Synchronized + timers.target loaded active active Timers + umount.target loaded inactive dead Unmount All Filesystems + batterycheck.timer loaded active waiting Update timer for locate database + borgbackup-job-nlaptop.timer loaded active waiting borgbackup-job-nlaptop.timer + btrbk-home.timer loaded active waiting Timer to take BTRFS snapshots and maintain retention policies. + btrbk-remote.timer loaded active waiting Timer to take BTRFS snapshots and maintain retention policies. + btrfs-autobalance.timer loaded active waiting btrfs-autobalance.timer + systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +xxx loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'." diff --git a/test/bin/version_246/systemd-analyze b/test/bin/version_246/systemd-analyze new file mode 100755 index 0000000..ca7274c --- /dev/null +++ b/test/bin/version_246/systemd-analyze @@ -0,0 +1,4 @@ +#! /bin/sh + +echo "Startup finished in 5.081s (kernel) + 34min 41.211s (userspace) = 34min 46.292s +graphical.target reached after 12.154s in userspace" diff --git a/test/dbus_systemd_info.py b/test/dbus_systemd_info.py new file mode 100755 index 0000000..d0e0c74 --- /dev/null +++ b/test/dbus_systemd_info.py @@ -0,0 +1,157 @@ +#! /usr/bin/python3 + +""" +A little script to explore the D-Bus API of systemd. +""" + +from colors import color + +# https://raw.githubusercontent.com/pengutronix/monitoring-check-systemd-service/master/check-systemd-service + +try: + from gi.repository.Gio import DBusProxy, BusType +except ImportError as e: + print("Please install python3-gi") + raise e + +# https://lazka.github.io/pgi-docs/#Gio-2.0/classes/DBusProxy.html#Gio.DBusProxy + +# https://www.freedesktop.org/wiki/Software/systemd/dbus/ + +dbus = DBusProxy.new_for_bus_sync(BusType.SYSTEM, 0, None, + 'org.freedesktop.systemd1', + '/org/freedesktop/systemd1', + 'org.freedesktop.systemd1.Manager', None) + + +def load_unit(unit_name): + try: + loaded_unit = dbus.LoadUnit('(s)', unit_name) + except Exception as e: + raise e + + return DBusProxy.new_for_bus_sync(BusType.SYSTEM, + 0, None, 'org.freedesktop.systemd1', + loaded_unit, + 'org.freedesktop.systemd1.Unit', None) + + +def get_unit_property(unit, property_name): + """ + :param unit: + https://www.freedesktop.org/wiki/Software/systemd/dbus/#unitobjects + """ + return unit.get_cached_property(property_name).unpack() + + +print(dbus.get_name()) +# org.freedesktop.systemd1 + +print(dbus.get_flags()) +# + +print(dbus.get_cached_property_names()) +# ['Architecture', 'ConfirmSpawn', 'ControlGroup', 'DefaultBlockIOAccounting', +# 'DefaultCPUAccounting', 'DefaultLimitAS', 'DefaultLimitASSoft', +# 'DefaultLimitCORE', 'DefaultLimitCORESoft', 'DefaultLimitCPU', +# 'DefaultLimitCPUSoft', 'DefaultLimitDATA', 'DefaultLimitDATASoft', +# 'DefaultLimitFSIZE', 'DefaultLimitFSIZESoft', 'DefaultLimitLOCKS', +# 'DefaultLimitLOCKSSoft', 'DefaultLimitMEMLOCK', 'DefaultLimitMEMLOCKSoft', +# 'DefaultLimitMSGQUEUE', 'DefaultLimitMSGQUEUESoft', 'DefaultLimitNICE', +# 'DefaultLimitNICESoft', 'DefaultLimitNOFILE', 'DefaultLimitNOFILESoft', +# 'DefaultLimitNPROC', 'DefaultLimitNPROCSoft', 'DefaultLimitRSS', +# 'DefaultLimitRSSSoft', 'DefaultLimitRTPRIO', 'DefaultLimitRTPRIOSoft', +# 'DefaultLimitRTTIME', 'DefaultLimitRTTIMESoft', 'DefaultLimitSIGPENDING', +# 'DefaultLimitSIGPENDINGSoft', 'DefaultLimitSTACK', 'DefaultLimitSTACKSoft', +# 'DefaultMemoryAccounting', 'DefaultOOMPolicy', 'DefaultRestartUSec', +# 'DefaultStandardError', 'DefaultStandardOutput', 'DefaultStartLimitBurst', +# 'DefaultStartLimitIntervalUSec', 'DefaultTasksAccounting', 'DefaultTasksMax', +# 'DefaultTimeoutAbortUSec', 'DefaultTimeoutStartUSec', +# 'DefaultTimeoutStopUSec', 'DefaultTimerAccuracyUSec', 'Environment', +# 'ExitCode', 'Features', 'FinishTimestamp', 'FinishTimestampMonotonic', +# 'FirmwareTimestamp', 'FirmwareTimestampMonotonic', +# 'GeneratorsFinishTimestamp', 'GeneratorsFinishTimestampMonotonic', +# 'GeneratorsStartTimestamp', 'GeneratorsStartTimestampMonotonic', +# 'InitRDGeneratorsFinishTimestamp', +# 'InitRDGeneratorsFinishTimestampMonotonic', 'InitRDGeneratorsStartTimestamp', +# 'InitRDGeneratorsStartTimestampMonotonic', 'InitRDSecurityFinishTimestamp', +# 'InitRDSecurityFinishTimestampMonotonic', 'InitRDSecurityStartTimestamp', +# 'InitRDSecurityStartTimestampMonotonic', 'InitRDTimestamp', +# 'InitRDTimestampMonotonic', 'InitRDUnitsLoadFinishTimestamp', +# 'InitRDUnitsLoadFinishTimestampMonotonic', 'InitRDUnitsLoadStartTimestamp', +# 'InitRDUnitsLoadStartTimestampMonotonic', 'KExecWatchdogUSec', +# 'KernelTimestamp', 'KernelTimestampMonotonic', 'LoaderTimestamp', +# 'LoaderTimestampMonotonic', 'LogLevel', 'LogTarget', 'NFailedJobs', +# 'NFailedUnits', 'NInstalledJobs', 'NJobs', 'NNames', 'Progress', +# 'RebootWatchdogUSec', 'RuntimeWatchdogUSec', 'SecurityFinishTimestamp', +# 'SecurityFinishTimestampMonotonic', 'SecurityStartTimestamp', +# 'SecurityStartTimestampMonotonic', 'ServiceWatchdogs', 'ShowStatus', +# 'SystemState', 'Tainted', 'TimerSlackNSec', 'UnitPath', +# 'UnitsLoadFinishTimestamp', 'UnitsLoadFinishTimestampMonotonic', +# 'UnitsLoadStartTimestamp', 'UnitsLoadStartTimestampMonotonic', +# 'UserspaceTimestamp', 'UserspaceTimestampMonotonic', 'Version', +# 'Virtualization'] + +print(dbus.get_cached_property('Version')) +# '245.4-4ubuntu3.2' + +# print(dbus.ListUnits()) + +# https://www.freedesktop.org/wiki/Software/systemd/dbus/ +# ListUnits() returns an array with all currently loaded units. Note that units +# may be known by multiple names at the same name, and hence there might be +# more unit names loaded than actual units behind them. The array consists of +# structures with the following elements: + + +def print_unit_structure(description, value): + """Print a value of the structure returned by ListUnits()""" + print("{}: {}".format(color(description, fg='green'), + color(value, fg='yellow'))) + + +def print_unit_property(dbus_unit, property_name): + """Print a property of the dbus unit object""" + print("{}: {}".format(color(property_name, fg='blue'), + get_unit_property(dbus_unit, property_name))) + + +# ('time-set.target', 'System Time Set', 'loaded', 'active', 'active', '', +# '/org/freedesktop/systemd1/unit/time_2dset_2etarget', 0, '', '/') +for (name, description, load, active, sub_state, followed_unit, object_path, + job_id, job_type, job_object_path) in dbus.ListUnits(): + print('\n{}\n'.format(color(name, fg='red'))) + + # The primary unit name as string + print_unit_structure("Primary unit name", name) + + # The human readable description string + print_unit_structure("Human readable description", description) + + # The load state (i.e. whether the unit file has been loaded successfully) + print_unit_structure("The load state", load) + + # The active state (i.e. whether the unit is currently started or not) + print_unit_structure("The active state", active) + + # The sub state (a more fine-grained version of the active state that is + # specific to the unit type, which the active state is not) + print_unit_structure("The sub state", sub_state) + + # A unit that is being followed in its state by this unit, if there is any, + # otherwise the empty string. + print_unit_structure("The followed unit", followed_unit) + + print_unit_structure("The unit object path", object_path) + + # If there is a job queued for the job unit the numeric job id, 0 otherwise + print_unit_structure("The numeric job id", job_id) + + # The job type as string + print_unit_structure("The job type", job_type) + + print_unit_structure("The job object path", job_object_path) + + dbus_unit = load_unit(name) + + print_unit_property(dbus_unit, 'ActiveState') diff --git a/test/test_doc.py b/test/test_doc.py new file mode 100644 index 0000000..e76061f --- /dev/null +++ b/test/test_doc.py @@ -0,0 +1,48 @@ +import unittest +from check_systemd import get_argparser + + +def argparser_to_readme(argparser, template='README-template.md', + destination='README.md', indentation=0, + placeholder='{{ argparse }}'): + """Add the formatted help output of a command line utility using the + Python module `argparse` to a README file. Make sure to set the name + of the program (`prop`) or you get strange program names. + + :param object argparser: The argparse parser object. + :param str template: The path of a template text file containing the + placeholder. Default: `README-template.md` + :param str destination: The path of the destination file. Default: + `README.me` + :param int indentation: Indent the formatted help output by X spaces. + Default: 0 + :param str placeholder: Placeholder string that gets replaced by the + formatted help output. Default: `{{ argparse }}` + """ + help_string = argparser().format_help() + + if indentation > 0: + indent_lines = [] + lines = help_string.split('\n') + for line in lines: + indent_lines.append(' ' * indentation + line) + + help_string = '\n'.join(indent_lines) + + with open(template, 'r', encoding='utf-8') as template_file: + template_string = template_file.read() + readme = template_string.replace(placeholder, help_string) + + readme_file = open(destination, 'w') + readme_file.write(readme) + readme_file.close() + + +class TestDoc(unittest.TestCase): + + def test_doc(self): + argparser_to_readme(argparser=get_argparser) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_mock.py b/test/test_mock.py new file mode 100644 index 0000000..06b48d3 --- /dev/null +++ b/test/test_mock.py @@ -0,0 +1,26 @@ +import unittest +from unittest import mock +import check_systemd + + +def mock_main(argv=['check_systemd.py'], stdout=None, stderr=None): + with mock.patch('sys.exit') as sys_exit, \ + mock.patch('check_systemd.subprocess.Popen') as Popen, \ + mock.patch('sys.argv', argv): + process = Popen.return_value + process.communicate.return_value = (stdout, stderr) + check_systemd.main() + + return {'sys_exit': sys_exit} + + +@unittest.skip('TODO mock second call of subprocess.Popen') +class TestMock(unittest.TestCase): + + def test_ok(self): + result = mock_main() + result['sys_exit'].assert_called_with(0) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_subprocess.py b/test/test_subprocess.py new file mode 100644 index 0000000..3f4dab8 --- /dev/null +++ b/test/test_subprocess.py @@ -0,0 +1,510 @@ +import unittest +import os +import subprocess + + +class AddBin(object): + """ + :param string bin_path: Path relative to the test folder. + """ + + def __init__(self, bin_path): + self.bin_path = bin_path + self.old_path = os.environ['PATH'] + + def __enter__(self): + BIN = os.path.abspath(os.path.join(os.path.dirname(__file__), + self.bin_path)) + os.environ['PATH'] = BIN + ':' + os.environ['PATH'] + + def __exit__(self, exc_type, exc_value, traceback): + os.environ['PATH'] = self.old_path + + +class TestOk(unittest.TestCase): + + def test_ok(self): + with AddBin('bin/ok'): + process = subprocess.run( + ['./check_systemd.py'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all ' + '| count_units=386 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + def test_ok_verbose(self): + with AddBin('bin/ok'): + process = subprocess.run( + ['./check_systemd.py', '--verbose'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all\n' + 'ok: all\n' + 'ok: startup_time is 12.15\n' + '| count_units=386 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + +class TestFailure(unittest.TestCase): + + def test_failure(self): + with AddBin('bin/failure'): + process = subprocess.run( + ['./check_systemd.py'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - smartd.service: failed ' + '| count_units=3 startup_time=12.154;60;120 ' + 'units_activating=0 units_active=1 units_failed=1 ' + 'units_inactive=1\n' + ) + + def test_failure_verbose(self): + with AddBin('bin/failure'): + process = subprocess.run( + ['./check_systemd.py', '-v'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - smartd.service: failed\n' + 'critical: smartd.service: failed\n' + '| count_units=3 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=1 units_failed=1 units_inactive=1\n' + ) + + +class TestMultipleFailure(unittest.TestCase): + + def test_failure_multiple(self): + with AddBin('bin/multiple_failure'): + process = subprocess.run( + ['./check_systemd.py'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - rtkit-daemon.service: failed, smartd.service: ' + 'failed | count_units=3 startup_time=46.292;60;120 ' + 'units_activating=0 units_active=1 units_failed=2 ' + 'units_inactive=0\n' + ) + + def test_failure_multiple_verbose(self): + with AddBin('bin/multiple_failure'): + process = subprocess.run( + ['./check_systemd.py', '--verbose'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - rtkit-daemon.service: failed, ' + 'smartd.service: failed\n' + 'critical: rtkit-daemon.service: failed\n' + 'critical: smartd.service: failed\n' + '| count_units=3 startup_time=46.292;60;120 units_activating=0 ' + 'units_active=1 units_failed=2 units_inactive=0\n' + ) + + +class TestCli(unittest.TestCase): + + def test_exclusive_group(self): + process = subprocess.run( + ['./check_systemd.py', '-u', 'test1.service', '-e', + 'test2.service'], + encoding='utf-8', + stderr=subprocess.PIPE + ) + self.assertEqual(process.returncode, 2) + self.assertIn( + 'error: argument -e/--exclude: not allowed with argument ' + '-u/--unit', + process.stderr, + ) + + def test_option_critical(self): + with AddBin('bin/ok'): + process = subprocess.run( + ['./check_systemd.py', '-c', '1'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - startup_time is 12.15 (outside range 0:1) ' + '| count_units=386 startup_time=12.154;60;1 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + def test_option_warning(self): + with AddBin('bin/ok'): + process = subprocess.run( + ['./check_systemd.py', '-w', '2'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 1) + self.assertEqual( + process.stdout, + 'SYSTEMD WARNING - startup_time is 12.15 (outside range 0:2) ' + '| count_units=386 startup_time=12.154;2;120 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + def test_option_no_startup_time_long(self): + with AddBin('bin/ok'): + process = subprocess.run( + ['./check_systemd.py', '-c', '1', '--no-startup-time'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all | ' + 'count_units=386 startup_time=12.154 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + def test_option_no_startup_time_short(self): + with AddBin('bin/ok'): + process = subprocess.run( + ['./check_systemd.py', '-c', '1', '-n'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + + def test_option_exclude_known_service(self): + with AddBin('bin/failure'): + process = subprocess.run( + ['./check_systemd.py', '-e', 'smartd.service'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all | count_units=2 startup_time=12.154;60;120 ' + 'units_activating=0 units_active=1 units_failed=0 ' + 'units_inactive=1\n' + ) + + def test_option_exclude_unknown_service(self): + with AddBin('bin/failure'): + process = subprocess.run( + ['./check_systemd.py', '-e', 'testX.service'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - smartd.service: failed | count_units=3 ' + 'startup_time=12.154;60;120 ' + 'units_activating=0 units_active=1 units_failed=1 ' + 'units_inactive=1\n' + ) + + def test_option_exclude_regexp(self): + with AddBin('bin/regexp_excludes'): + process = subprocess.run( + ['./check_systemd.py', '-e', 'user@\\d+\\.service'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all | count_units=2 ' + 'startup_time=12.154;60;120 ' + 'units_activating=0 units_active=1 units_failed=0 ' + 'units_inactive=1\n' + ) + + def test_option_exclude_regexp_dot(self): + with AddBin('bin/regexp_excludes'): + process = subprocess.run( + ['./check_systemd.py', '-e', '.*'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all | count_units=0 ' + 'startup_time=12.154;60;120 ' + 'units_activating=0 units_active=0 units_failed=0 ' + 'units_inactive=0\n' + ) + + def test_option_version(self): + process = subprocess.run( + ['./check_systemd.py', '--version'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertIn('check_systemd', process.stdout) + + def test_option_help(self): + process = subprocess.run( + ['./check_systemd.py', '--help'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertIn('check_systemd', process.stdout) + + def test_entry_point(self): + process = subprocess.run( + ['check_systemd', '--help'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertIn('check_systemd', process.stdout) + + +class TestOptionUnit(unittest.TestCase): + + def test_option_unit_ok(self): + with AddBin('bin/is_active/active'): + process = subprocess.run( + ['./check_systemd.py', '-u', 'test.service'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - test.service: active\n' + ) + + def test_option_unit_failed(self): + with AddBin('bin/is_active/failed'): + process = subprocess.run( + ['./check_systemd.py', '--unit', 'test.service'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - test.service: failed\n' + ) + + def test_option_unit_inactive(self): + with AddBin('bin/is_active/inactive'): + process = subprocess.run( + ['./check_systemd.py', '--unit', 'test.service'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - test.service: inactive\n' + ) + + def test_option_ignore_inactive_state(self): + with AddBin('bin/is_active/inactive'): + process = subprocess.run( + ['./check_systemd.py', '--unit', 'test.service', + '--ignore-inactive-state'], + encoding='utf-8', + stdout=subprocess.PIPE + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - test.service: inactive\n' + ) + + +class TestBootupNotFinished(unittest.TestCase): + + def test_bootup_not_finished(self): + with AddBin('bin/bootup_not_finished'): + process = subprocess.run( + ['./check_systemd.py'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all ' + '| count_units=386 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + def test_bootup_not_finished_verbose(self): + with AddBin('bin/bootup_not_finished'): + process = subprocess.run( + ['./check_systemd.py', '--verbose'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all\n' + 'ok: all\n' + '| count_units=386 units_activating=0 ' + 'units_active=275 units_failed=0 units_inactive=111\n' + ) + + +class TestDeadTimers(unittest.TestCase): + + def test_dead_timers_1(self): + with AddBin('bin/dead_timers_1'): + process = subprocess.run( + ['./check_systemd.py', '-t'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - phpsessionclean.timer ' + '| count_units=3 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=3 units_failed=0 units_inactive=0\n' + ) + + def test_dead_timers_2(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - dfm-auto-jf.timer, ' + 'rsync.timer ' + '| count_units=3 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=3 units_failed=0 units_inactive=0\n' + ) + + def test_dead_timers_2_ok(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t', '-W', '2764801', '-C', '2764802'], + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + + def test_dead_timers_2_warning(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t', '-W', '2764799', '-C', '2764802'], + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 1) + + def test_dead_timers_2_warning_equal(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t', '-W', '2764800', '-C', '2764802'], + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 1) + + def test_dead_timers_ok(self): + with AddBin('bin/dead_timers_ok'): + process = subprocess.run( + ['./check_systemd.py', '-t'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + self.assertEqual( + process.stdout, + 'SYSTEMD OK - all ' + '| count_units=3 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=3 units_failed=0 units_inactive=0\n' + ) + + def test_dead_timers_exclude(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t', '-e', 'dfm-auto-jf.timer'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - rsync.timer ' + '| count_units=3 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=3 units_failed=0 units_inactive=0\n' + ) + + def test_dead_timers_exclude_multiple(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t', + '-e', 'dfm-auto-jf.timer', + '-e', 'rsync.timer'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + + def test_dead_timers_exclude_regexp(self): + with AddBin('bin/dead_timers_2'): + process = subprocess.run( + ['./check_systemd.py', '-t', '-e', '.*timer'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 0) + + +class TestVersion246(unittest.TestCase): + + def test_version_246(self): + with AddBin('bin/version_246'): + process = subprocess.run( + ['./check_systemd.py'], + encoding='utf-8', + stdout=subprocess.PIPE, + ) + self.assertEqual(process.returncode, 2) + + self.assertEqual( + process.stdout, + 'SYSTEMD CRITICAL - nm-wait-online.service: failed | ' + 'count_units=339 startup_time=12.154;60;120 units_activating=0 ' + 'units_active=263 units_failed=1 units_inactive=75\n' + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_unit.py b/test/test_unit.py new file mode 100644 index 0000000..22b8410 --- /dev/null +++ b/test/test_unit.py @@ -0,0 +1,48 @@ +import unittest +import check_systemd +from check_systemd import TableParser + + +class TestUnit(unittest.TestCase): + + def test_function_format_timespan_to_seconds(self): + _to_sec = check_systemd.format_timespan_to_seconds + self.assertEqual(_to_sec('1s'), 1) + self.assertEqual(_to_sec('1s ago'), 1) + self.assertEqual(_to_sec('11s'), 11) + self.assertEqual(_to_sec('1min 1s'), 61) + self.assertEqual(_to_sec('1min 1.123s'), 61.123) + self.assertEqual(_to_sec('1min 2.15s'), 62.15) + self.assertEqual(_to_sec('34min 46.292s'), 2086.292) + self.assertEqual(_to_sec('2 months 8 days'), 5875200) + + +class TestTableParser(unittest.TestCase): + + def setUp(self): + self.heading = 'UNIT LOAD ACTIVE SUB DESCRIPTION' + self.row = 'unit+load+1234active sub+description' + self.parser = TableParser(self.heading) + + def assert_column(self, column_title, result): + self.assertEqual(self.parser.get_column_text(self.row, column_title), + result) + + def test_get_column_text_unit(self): + self.assert_column('UNIT', 'unit+') + + def test_get_column_text_load(self): + self.assert_column('LOAD', 'load+1234') + + def test_get_column_text_active(self): + self.assert_column('ACTIVE', 'active') + + def test_get_column_text_sub(self): + self.assert_column('SUB', 'sub+') + + def test_get_column_text_description(self): + self.assert_column('DESCRIPTION', 'description') + + +if __name__ == '__main__': + unittest.main() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..b20d675 --- /dev/null +++ b/tox.ini @@ -0,0 +1,30 @@ +[tox] +envlist = py36, py37, py38, py39, flake8, docs + +[testenv] +deps = nose +commands = nosetests --nocapture {posargs} + +[testenv:py36] +basepython = python3.6 + +[testenv:py37] +basepython = python3.7 + +[testenv:py38] +basepython = python3.8 + +[testenv:py39] +basepython = python3.9 + +[testenv:flake8] +basepython = python3.8 +deps = flake8 +commands = flake8 check_systemd.py test setup.py + +[testenv:docs] +basepython = python3.8 +deps = + sphinx + sphinx_rtd_theme +commands = sphinx-build -q -b html doc/source {envtmpdir}/html