pax_global_header00006660000000000000000000000064132572552260014523gustar00rootroot0000000000000052 comment=be0ac81e5664f481e3de3b8a4d76c0867659d7b1 needrestart-3.1/000077500000000000000000000000001325725522600137065ustar00rootroot00000000000000needrestart-3.1/.gitignore000066400000000000000000000001741325725522600157000ustar00rootroot00000000000000autom4te.cache/ debian/ man/Makefile perl/MYMETA.json perl/MYMETA.yml perl/Makefile perl/blib/ perl/pm_to_blib po/.build *~ needrestart-3.1/AUTHORS000066400000000000000000000000751325725522600147600ustar00rootroot00000000000000needrestart =========== Thomas Liske needrestart-3.1/COPYING000066400000000000000000000431221325725522600147430ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 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. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 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 Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; 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. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. needrestart-3.1/ChangeLog000066400000000000000000000642471325725522600154750ustar00rootroot00000000000000needrestart (3.1) unstable; urgency=high * Changes: - [uCode] Handle microcode upgrades in early boot initrd images, required at least on Arch Linux. (github issue #106 by @Wuestengecko) * Fixes: - [uCode] Fix uninitialized value in batch mode. (Debian Bug#891923 by Bob Proulx ) (github issue #105 by Evgenii Terechkov @evgkrsk) - [uCode] Fix completely broken microcode update detection. (github issue #108 by @Wuestengecko) - [UI] Fix microcode revision placeholders in NeedRestart::UI::stdio. -- Thomas Liske Thu, 29 Mar 2018 23:22:55 +0200 needrestart (3.0) unstable; urgency=medium * Features: - [Core] Possible to suspend needrestart in apt-get hook using the NEEDRESTART_SUSPEND environment variable. (github issue #71 by Ludovic Gasc @GMLudo et. al.) - [Core] Possible to override the configured restart mode using the NEEDRESTART_MODE environment variable. (Debian Bug#866105 by Marc Haber ) - [uCode] Check for pending Intel microcode updates. (Debian Bug#886445 by Paul Wise ) * Changes: - [Core] Do not try to restart service units with RefuseManualStop=yes. (github issue #75 by Marc Dequènes @duck-rh) - [Kernel] Try to adopt RPM's version sorting to get most recent kernel. (github issue #73 by Maximilian Gaß @mxey) - [Core] Tune blacklist_mappings default setting to match on deleted maps. - [UI] Respect verbosity in UI::stdio, just like UI::Debconf. (github pull request #88 by @guillaume-uH57J9) - [Core] Improve output formating. (github issue #84 by Stavros Ntentos @stdedos) - [Core] Improve container detection to skip kernel and microcode checks. * Fixes: - [Core] Makefile: Fix installation of restart.d/ scripts. (Debian Bug#851866 by Sven Hartge ) - [Core] Fix warning in Perl 5.20.x, not triggered in 5.24.x in needrestart.conf (Oil Runtime Compiler's JIT files). (patch by Patrick Matthäi (Debian)) - [Core] Do not restart oneshot services. (Debian Bug#862840 by Alan Jenkins ) - [Core] Ignore rc-local.service. (Debian Bug#852864 by Paul Wise ) - [Core] Do not restart libvirt by default. (github issue #69 by Craig Andrews @candrews) - [Interp/Perl] Add missing cwd restore before a return. (github issues #55 and #70 Craig Andrews @candrews and Stefan Bühler @stbuehler) - [Core] README.md: Fix spelling. (github issue #74 by Edward Betts @EdwardBetts) - [Core] Add bird to override. (github issue #78 by Björn Lässig @Farom) - [Interp/(Perl|Python)] Use absolute paths used to search the package of a script file. (github issue #79 by Christopher Odenbach @odenbach) - [Hook] Use rpm -q --filesbypkg rather than rpmquery. (github issue #81 by Sven Hartge @shartge) - [CONT] Detect docker container ns running not on systemd. - [CONT] Ignore processes running inside docker containers. (github issue #80 by Christopher Odenbach @odenbach) - [Core] Ignore special filename mappings used by recent versions of KDE plasmashell. (github issue #65 by @GoTeamAnt) (Debian Bug#879091 by Paul Wise ) - [Core] Fix handling of library mappings if target does not exist. (github issue #58 by @pigen) (Debian Bug#878700 by Richard Hector ) - [Hook] Fix handling of multiarch packages. (github issue #56 by @mayasd) - [Interp] Ignore interpreter processes with unreachable root fs (i.e. in different mnt ns). (github issue #72 by Stefan Bühler @stbuehler) - [Core] Add missing unnamed device major numbers (fix for OpenVZ). (Debian Bug#876452 by Piotr Pańczyk ) - [UI] Do not call GetTerminalSize() if STDOUT is not a TTY. (Debian Bug#859387 by by Paul Wise ) (github issues #85 and #86 by @guillaume-uH57J9) - [UI] Fix switch from interactive to list mode if debconf is run noninteractive. (Debian Bug#876459 by Piotr Pańczyk ) - [man] Add documentation on restart mode if run non-interactive. (Debian Bug#842512 by Antoine Beaupré ) - [Core] Ignore some Java false positives (JNA, JFFI). (github pull request #89 by Maximilian Gaß @mxey) (github issue #60 by @ge-fa) - [Core] Output NRPE message "root needed" on stdout. (github pull request #91 by @nirgal) - [Core] Use override_cont when querying containers. (github pull request #94 by Nigel Kukard @nkukard) - [Core] Do not restart docker by default. - [Core] Fix typo in man page. (Debian Bug#885448 by Paul Wise ) - [Interp] Fix perl warning if cwd is unreachable. (github issue #99 by @glitsj16) - [Hook] Replace remaining calls of rpmquery by rpm. (github issue #100 by Matthias Hörmann @taladar) - [Core] Fix additional unit detection in dbus restart handler. (github issue #104 by Alexander Barton @alexbarton) -- Thomas Liske Fri, 23 Feb 2018 13:38:46 +0100 needrestart (2.11) unstable; urgency=medium * Features: - [Core] Allow special treatment to restart services (i.e. dbus). (github issue #44 by @Vladimir-csp) - [Cont] Support restarting LXD-based LXC containers. (github issue #26 by James Johnston @JohnstonJ) - [Core] New config option to enforce legacy session detection if systemd is used without PAM integration. (github issue #52 by @micw and Eric S. @Korni22) * Fixes: - [Core] Fix default config type for override_* settings. (github issue #47 by @mphilipps) - [Kernel] Ignore initrd filenames while looking for kernel image files. (github issue #49 by Evgenii Terechkov @evgkrsk) - [Kernel] Strip .img from version string when deducting the kernel version from filename. (github issue #49 by Evgenii Terechkov @evgkrsk) - [Core] Fix wrong regex quotation in default configuration file. (Debian Bug#844283 by Paul Wise ) - [Core] Add display-manager 'lxdm' to override. (Debian Bug#845996 by Rodrigo Campos ) - [Interp] Make paths when searching source files relative to the root path of the process. (github issue #54 by Tomasz Kontusz @ktosiek) -- Thomas Liske Tue, 17 Jan 2017 15:59:36 +0100 needrestart (2.10) unstable; urgency=medium * Features: - [Interp] Allow ignoring of interpreted files. (github issue #39 by Wolfgang Karall @wolfgangkarall) - [Core] Make verification of mapped files in fileystem configurable as a workaround for broken grsecurity kernels. (github issue #46 by @jleroy @eigengrau) - [Core] Make ignore of mapped files configurable. (github issue #45 by @stbuehler) * Fixes: - [Core] Do not ignore processes if maps file could not be read. - [Perl] Silence warnings of Module::ScanDeps for dynamic loaded modules. (github issue #41 by @bxkx @r-lindner) - [UI] Do not use Text::Wrap while printing restart commands. (Debian Bug#838622 by Paul Wise ) - [Core] Do really restart services in automatic mode. (Debian Bug#838355 by Georg ) - [Kernel] Include /boot/*.img while looking for linux kernel images. Fixes kernel detection on Raspbian. (github issue #38 by @fenhl) -- Thomas Liske Thu, 03 Nov 2016 23:37:05 +0100 needrestart (2.9) unstable; urgency=medium * Changes: - [l10n] Add RU translation for notify.d stuff. (github issue #29 by @Vladimir-csp) (github issue #31 by @Vladimir-csp) - [Conf] Add lxcfs to override_rc. (Debian Bug#832166 by Evgeni Golov ) - [Conf] Pass arguments of apt-pinvoke to needrestart. (Debian Bug#826220 by Wolfgang Karall-Ahlborn ) - [Core] Use $(MAKE) instead of make for parallel make. (github issue #34 by Craig Andrews @candrews) - [Core] Make nagios severities configurable. (github issue #32 by Christoph Anton Mitterer @calestyo) * Features: - [Core] Sys-V: use chkconfig tags if LSB tags are missing. (github issue #33 by Evgenii Terechkov @evgkrsk) - [Interp] Cache file lists of interpreter processes. (Debian Bug#826247 by Wolfgang Karall-Ahlborn ) * Fixes: - [UI] Add a workaround for bug in Term::ReadKey if STDOUT does not print on a TTY (see also Debian Bug#824564). - [Core] Fix orcexec regex to match on removed files, too. (Debian Bug#828103 by Paul Wise ) - [Core] Don't compare device numbers on anon fs (i.e. OpenVZ's simfs). (github issue #28 by Sven-Haegar Koch @haegar) - [Core] Fix odd perl warnings about LSB tags. (github issue #33 by Evgenii Terechkov @evgkrsk) - [Core] Make systemctl_combine config option working. (Debian Bug#826526 by Paul Wise ) - [Core] Handle newlines in kernel versions gracefully. (Debian Bug#827162 by Martin Steigerwald ) - [Core] Fix session counter in nagios plugin mode. -- Thomas Liske Sat, 03 Sep 2016 14:52:41 +0200 needrestart (2.8) unstable; urgency=medium * Changes: - [Core] Restart SysV init services on systemd using systemctl. (Debian Bug#818853 by Paul Wise ) - [Core] Print a combined `systemctl restart` command line for skipped services (config option). (Debian Bug#818853 by Paul Wise ) - [l10n] Make NeedRestart::UI::stdio localized and update German localization. - [notify] Disable mail notification by default (notify.conf). * Features: - [Core] Add a easy UI mode hiding technical details for non-technical users. (Debian Bug#819824 by Patrick Schleizer )) - [Cont] Detect systemd-machined containers. * Fixes: - [Conf] Add xendomains to override_rc. (Debian Bug#817807 by Samuel Thibault ) - [Core] Do not terminate debconf after restart service selection since it is still needed for container selection. - [Core] Fix regex handling in cgroup detection. (github pull request #25 by Courtney Bane @cbane) - [Core] Fix library probing inside filesystem namespaces (i.e. LXC containers). (github issue #23 by Lukas Pirl @lpirl) - [Interp] Fix incomplete skipping of scanning files in Interp/*.pm if cwd is unknown. - [Interp] Improve getopts parsing (Interp::*) to remove "Uknown option:" warnings. (Debian Bug#817927 by F. Petitjean ) - [notify.d] Fix bashisms in /etc/needrestart/notify.d/*. (Debian Bug#818001 by Cristian Ionescu-Idbohrn ) (github issue #21 by Sebastian Brandt @sbrandtb) (Debian Bug#824184 by Axel Beckert ) - [UI] stdio: do not skip service asked while choosing auto mode. -- Thomas Liske Mon, 16 May 2016 18:45:51 +0200 needrestart (2.7) unstable; urgency=medium * [Bug] Ignore init rc being symlinks to upstart-job. (github issue #16 by Jonas Genannt @hggh) * [Bug] Allow systemd service names with dots in them. (github issue #19 by Michael Fladischer ) * [Bug] Add display-manager 'slim' to override. (Debian Bug#816061 by Lars Kruse ) * [debconf] Add russian translation. (Debian Bug#815086 by Vladimir Kudrya ) * [notify] Add support for translation of notify scripts. (Debian Bug#815086 by Vladimir Kudrya ) * [Core] Add support for translation of core script. (Debian Bug#815086 by Vladimir Kudrya ) * [Bug] Fix missing translations in debconf template file. (Debian Bug#815086 by Vladimir Kudrya ) * [notify] Notification scripts can be disabled globaly (see notify.conf). (Debian Bug#787297 by Christoph Anton Mitterer ) * [Core] Improve output of restart commands. -- Thomas Liske Sun, 06 Mar 2016 14:46:45 +0100 needrestart (2.6) unstable; urgency=high * [Bug] Do not notify system users via email. (Debian Bug#812399 by Marc Haber ) * [Bug] Do no restart services in interactive restart mode while debconf's noninteractive frontend is used. (Debian Bug#803249 by Felix Geyer ) * [Bug] Fix broken detection of old mappings due to regression introduced in v2.3 (commit acf6a07). (Debian Bug#810970 by Andreas Schmidt ) -- Thomas Liske Wed, 17 Feb 2016 22:14:32 +0100 needrestart (2.5) unstable; urgency=medium * [Bug] Fix broken kernel detection due to syntax error. (Debian Bug#810031 by Martin Steigerwald ) -- Thomas Liske Tue, 05 Jan 2016 23:17:53 +0100 needrestart (2.4) unstable; urgency=medium * [Bug] Drop unused dependency on File::Slurp. (Debian Bug#799733 by Christoph Anton Mitterer ) (Debian Bug#799734 by Sven Hartge ) * [Bug] Add user@\d+.service to override_rc. (Debian Bug#788380 by Shirish Agarwal ) * [Bug] Add override for systemd-logind due to another systemd regression. (Debian Bug#800718 by Sven Hartge ) * [Bug] Fix grammar in hook scripts. (Debian Bug#805980 by Justin B Rye ) * [Bug] Fix kernel detection on non x86* arch. (Debian Bug#800720 by Sven Hartge ) * [Kernel] Extract kernel version on non-x86(_64) archs (allows ABI checks). -- Thomas Liske Fri, 01 Jan 2016 21:54:47 +0100 needrestart (2.3) unstable; urgency=medium * [Bug] Add lightdm to override. (Debian Bug#791649 by Martin Steigerwald ) * [Bug] Do not try container detection in user mode. (Debian Bug#791665 by Ansgar Burchardt ) * [Bug] Remove unsupported HTML markups from notifications. (Debian Bug#791664 by Ansgar Burchardt ) * [Bug] Compare inodes of mapped files more reliable for chrooted processes. (github issue #11 by Markus Frosch ) * [Kernel] Skip kernel detection within containers. * [UI] Add a quiet option to drop any progress messages. (Debian Bug#791708 by Rodrigo Campos ) * [Bug] Do not handle user services as system services. (Debian Bug#792032 by Ansgar Burchardt ) * [Bug] Fix cutting path names read from /proc/PID/maps at spaces resulting in false-positives. -- Thomas Liske Sat, 19 Sep 2015 20:38:19 +0200 needrestart (2.2) unstable; urgency=medium * [regression] Processes using chroot were always detected as obsolete since missing binaries in /proc/PID/root/. (Debian Bug#786584 by François Mescam ) -- Thomas Liske Tue, 26 May 2015 23:56:11 +0200 needrestart (2.1) unstable; urgency=medium * [Bug] Ignore /usr/bin/apt-get. (Debian Bug#784237 by Thijs Kinkhorst ) * [Bug] Add override for systemd's emergency.service and rescue.service. (Debian Bug#784437) * [Bug] Ignore Oil Runtime Compiler's JIT files. (Debian Bug#786374 by Francois Mescam ) * [Bug] Fix 2c037bc did broke the progressbar. (Related to Debian Bug#768124) * [Cont] Detect and suggest to restart containers: - docker - LXC (Debian Bug#783181 by Brian Minton ) * [Core] Add nagios plugin mode (-p). (github issue #5 by Ludovic Gasc [@GMLudo]) * [Core] Use /proc/$PID/root to scan for files fixing false positives on containers (i.e. LXC) using bind mounts. (Debian Bug#783181 by Brian Minton ) * [Interp] Skip scanning files with Interp/* if cwd is unknown. (Debian Bug#779832 by wforumw ) * [Interp] Skip scanning files with Interp/* if cwd is unknown. (Debian Bug#779832 by wforumw ) * [Kernel] Add kernel hints option not requiring an acknowledgement by the user. (Debian Bug#769811 by Axel Beckert ) * [Kernel] Take version number comparing stuff from Dpkg::Version to compare kernel versions correctly. (Debian Bug#781657 by Martin Steigerwald ) * [UI] Improve restart query in interactive mode (stdio). (Debian Bug#772859 by Axel Beckert ) -- Thomas Liske Fri, 22 May 2015 01:45:17 +0200 needrestart (2.0) unstable; urgency=medium * [regression] List commands in list mode. (Debian Bug#764042 by Paul Wise ) * Add a conf.d/ directory. (Debian Bug#764043 by Paul Wise ) * [UI] Fix empty current/expected kernel version string used by debconf template. (Debian Bug#764917 by Laurent Bonnaud ) * Don't blacklist services by default but use a new override_rc option to don't restart some critical services by default. (Debian Bug#763937 by Christoph Anton Mitterer ) * Don't restart services greylisted in override_rc in auto mode. (Debian Bug#770937 by Axel Beckert ) * [UI] Disable progress bar while running non-interactive. (Debian Bug#768124 by Phillip Berndt ) * [UI] Fix warning on uninitialized values while reading from /dev/stdin. (Debian Bug#768124 by Phillip Berndt ) * [Interp] Add basic Java detection support. * Add PolicyKit action file to allow needrestart-session to run needrestart as root. * [UI] Add `-f ` CLI parameter to allow to overwrite the DEBIAN_FRONTEND environment variable used by debconf(7). -- Thomas Liske Fri, 23 Jan 2015 00:46:13 +0100 needrestart (1.2) unstable; urgency=medium * Prepare po-debconf usage and add German translation. (Debian Bug#761068 by David Prévot ) * Drop dependency on Term::ProgressBar::Simple. (Debian Bug#761192 by Thijs Kinkhorst ) * Fix blacklist to match upgraded binaries (dpkg). (Debian Bug#761346 by Paul Wise ) * Fix detection of unit names on systemd 215+. (Debian Bug#762312 by Sven Hartge ) * Ignore special paths (SYSV IPC, DRM, /dev), fixing some false positives. * Add service blacklist configuration option to fix display manager blacklisting with systemd. * Handle restarts of systemd manager and sysv init using their specific commands. (Debian Bug#762528 by Paul Wise ) -- Thomas Liske Sun, 28 Sep 2014 23:48:42 +0200 needrestart (1.1) unstable; urgency=medium * Ignore DHCP clients. (Debian Bug#752111 by Axel Beckert ) * Add options allowing to select which check should be performed. (Proposed by Axel Beckert ) -- Thomas Liske Sat, 16 Aug 2014 09:57:29 +0200 needrestart (1.0) unstable; urgency=medium * Fix grammar errors and use a additional debconf template. (Debian Bug#748652 by Justin B Rye ) * Ignore device ID in /proc//maps on kFreeBSD. (Reported by Axel Beckert ). * Ignore device ID for unnamed devices due to broken implementation on btrfs. (Debian Bug#750734 by Frederik Himpe ) * Skip scanning of needrestart process. (Debian Bug#751877 by Thijs Kinkhorst ) * [UI] Drop UI specific progress indicators, use Term::ProgressBar::Simple to minimize disruption of the terminal. (Debian Bug#748758 by Thijs Kinkhorst ) * [UI] Support 'backup' capability of Debconf. * [Interp] Fix include path retrieval on python3. (Debian Bug#750589 by Cristian Ionescu-Idbohrn ) * [Interp] Handle errors on python include path retrieval gracefully. (Debian Bug#750589 by Cristian Ionescu-Idbohrn ) -- Thomas Liske Tue, 17 Jun 2014 15:21:15 +0200 needrestart (0.9) unstable; urgency=medium * Drop external dependency on strings command from binutils. * Fix "uninitialized value" by apparent kernel threads. (Debian Bug#746363 by Axel Beckert ) * Read kernel version from x86 kernel boot header and handle uncompressed kernel images. (Debian Bug#746550 by Axel Beckert ) * Several small bugfixes: - [Interp] initial source file detection broken due using getopt instead of getopts (Debian Bug#746363 by Axel Beckert ) - [UI] fix newlines in Debconf template - [UI] fix "No such file or directory" triggered by stdio (Debian Bug#746550 by Axel Beckert ) - [Interp] Use source file instead of /proc//exe to find package. -- Thomas Liske Sun, 11 May 2014 22:48:42 +0200 needrestart (0.8) unstable; urgency=low * Fix non-numeric argument on progress_prep call. (Debian Bug#744961 by Cristian Ionescu-Idbohrn ) * Feature: interpreter support enables needrestart to look for obsolete source files in scripting languages: - Perl: using Module::ScanDeps - Python: using home made source file scanning - Ruby: using home made source file scanning * Feature: detect running on obsolete kernels (Debian Bug#745270 by Paul Wise ) * NeedRestart::UI::Dialog: has been dropped * NeedRestart::UI::stdio: add mass processing * Several small bugfixes. -- Thomas Liske Sun, 27 Apr 2014 10:15:35 +0200 needrestart (0.7) unstable; urgency=medium * Improved rc script detection, e.g.: previous releases failed to detect apache2's init script after upgrading libssl1.0.0. * Handle Linux VServer naming convention on deleted binaries. (Thanks to Phillip Berndt [@phillipberndt]) * Support GNU formatted device ids. (github issue #1 by Phillip Berndt [@phillipberndt]) * Hooks: Use only available package managers. * Hooks: Ignore hooks not returning any rc scripts (fixes detecting apache2's rc script). * Hooks: Prefer rc scripts w/ matching pid (fixes calling unnecessary rc scripts like libvirt-guests). * Improve rc script detection by using a two pass analysis. * Fallback to NeedRestart::UI::stdio while being verbose. (Debian Bug#744000 by Paul Wise ) * Add default UI configuration option. (Debian Bug#744001 by Paul Wise ) * Apply blacklist while processing parent processes. (Debian Bug#744002 by Paul Wise ) * Apply Debian's 01-makefile-fix.diff upstream. -- Thomas Liske Mon, 14 Apr 2014 21:50:15 +0200 needrestart (0.6) unstable; urgency=low * Add lightdm to blacklist. (Debian Bug#735027 by Michael Gilbert ) * Print eval exception message on config file errors. * Use systemd if available. (Debian Bug#731028 by Paul Wise ) * Use service to run traditional SysV scripts. * Change batch processing output. * Print full restart commands in list mode. (Debian Bug#731028 by Paul Wise ) -- Thomas Liske Mon, 07 Apr 2014 22:52:18 +0200 needrestart (0.5) unstable; urgency=low * Ignore mapped files in /tmp. * Handle LSB tags case insensitivly. (Debian Bug#731165 by Christian Ionescu-Idbohrn ) * Prevent config file in dpkg.cfg.d to break dpkg after removing needrestart. (Debian Bug#732461 by Andreas Beckmann ) -- Thomas Liske Thu, 02 Jan 2014 19:55:49 +0100 needrestart (0.4) unstable; urgency=low * Fix spelling: - typo in debconf template (s/restartet/restarted/;) (Debian Bug#723935 by Axel Beckert ) - debconf template title (s/orphaned/outdated/;) (Debian Bug#723935 by Justin B Rye ) * Fix progress bar increase to grow up to 100%: - binaries were counted twice - kernel threads did not increase progress * Demand restart of deleted binaries. * Add sudo binary to example blacklist. (Debian Bug#725937 by Jim Barber ) * Drop version number from man page. (Debian Bug#729997 by Raf Czlonka ) * NeedRestart::UI::Debconf: Fix return code handling if readline is used as debconf frontend. (Debian Bug#729997 by Raf Czlonka ) -- Thomas Liske Thu, 28 Nov 2013 19:30:06 +0100 needrestart (0.3) unstable; urgency=low * Fix typo reported by Patrick Matthäi. * Add man page provided by Patrick Matthäi (Debian). * Offer restart on non-existing mappings. * Add PacMan hook. * Be more fault-tolerant in batch mode. * Provide a more sophisticated apt/dpkg trigger. * Fix ignored -r command line parameter. (Debian Bug#721809 by Axel Beckert ) * Ignore forked/detached daemon childs (pidfile heuristic). (Debian Bug#721810 by Axel Beckert ) * Provide modular UI including debconf and dialog based frontends. * Ignore binaries due blacklist config option. -- Thomas Liske Sat, 14 Sep 2013 12:55:16 +0200 needrestart (0.2) unstable; urgency=low * Support (l)ist only, (i)nteractive restart and (a)utomaticly restart modes. * Supply apt.conf.d script to call needrestart on every upgrade. * Drop dependency on (Debian's) run-parts. * Drop Term::Query dependency. * Ignore rc scripts to be run in other run-levels. * Add batch mode. -- Thomas Liske Tue, 02 Apr 2013 21:51:48 +0200 needrestart (0.1) unstable; urgency=low * Initial release. -- Thomas Liske Fri, 29 Mar 2013 19:40:09 +0100 needrestart-3.1/INSTALL.md000066400000000000000000000004201325725522600153320ustar00rootroot00000000000000Prerequisites ============= Perl ---- - Module::Find - Module::ScanDeps - Locale::TextDomain - Proc::ProcessTable - Sort::Naturally - Term::ReadKey - Parent (for legacy Perl versions, i.e. on CentOS 6) Misc ---- - gettext - po-debconf (on Debian derivates) - xz-utils needrestart-3.1/Makefile000066400000000000000000000054131325725522600153510ustar00rootroot00000000000000LOCALEDIR=/usr/share/locale all: mo-files cd perl && perl Makefile.PL PREFIX=$(PREFIX) INSTALLDIRS=vendor cd perl && $(MAKE) install: all cd perl && $(MAKE) install mkdir -p "$(DESTDIR)/etc/needrestart/hook.d" cp hooks/* "$(DESTDIR)/etc/needrestart/hook.d/" cp ex/needrestart.conf "$(DESTDIR)/etc/needrestart/" cp ex/notify.conf "$(DESTDIR)/etc/needrestart/" mkdir -p "$(DESTDIR)/etc/needrestart/conf.d" cp ex/conf.d/* "$(DESTDIR)/etc/needrestart/conf.d/" mkdir -p "$(DESTDIR)/etc/needrestart/notify.d" cp ex/notify.d/* "$(DESTDIR)/etc/needrestart/notify.d/" mkdir -p "$(DESTDIR)/etc/needrestart/restart.d" cp ex/restart.d/* "$(DESTDIR)/etc/needrestart/restart.d/" which apt-get > /dev/null && \ mkdir -p "$(DESTDIR)/etc/apt/apt.conf.d" && cp ex/apt/needrestart-apt_d "$(DESTDIR)/etc/apt/apt.conf.d/99needrestart" && \ mkdir -p "$(DESTDIR)/etc/dpkg/dpkg.cfg.d" && cp ex/apt/needrestart-dpkg_d "$(DESTDIR)/etc/dpkg/dpkg.cfg.d/needrestart" && \ mkdir -p "$(DESTDIR)/usr/lib/needrestart" && cp ex/apt/dpkg-status ex/apt/apt-pinvoke "$(DESTDIR)/usr/lib/needrestart" || true which debconf > /dev/null && \ mkdir -p "$(DESTDIR)/usr/share/needrestart" && \ po2debconf ex/debconf/needrestart.templates > "$(DESTDIR)/usr/share/needrestart/needrestart.templates" || true mkdir -p "$(DESTDIR)/usr/share/polkit-1/actions" cp ex/polkit/net.fiasko-nw.needrestart.policy "$(DESTDIR)/usr/share/polkit-1/actions/" mkdir -p "$(DESTDIR)/usr/sbin" cp needrestart "$(DESTDIR)/usr/sbin/" mkdir -p "$(DESTDIR)/usr/lib/needrestart" cp lib/iucode-scan-versions "$(DESTDIR)/usr/lib/needrestart/" cp lib/vmlinuz-get-version "$(DESTDIR)/usr/lib/needrestart/" cp lib/notify.d.sh "$(DESTDIR)/usr/lib/needrestart/" mkdir -p "$(DESTDIR)$(LOCALEDIR)" cp -r po/.build/* "$(DESTDIR)$(LOCALEDIR)/" clean: [ ! -f perl/Makefile ] || ( cd perl && $(MAKE) realclean ) rm -rf po/.build pot-files: po/debconf/templates.pot po/needrestart/messages.pot po/needrestart-notify/messages.pot po/debconf/templates.pot: ex/debconf/needrestart.templates cd ex/debconf && debconf-updatepo touch -r $+ $@ po/needrestart/messages.pot: needrestart $(wildcard perl/lib/NeedRestart/Kernel/*.pm wildcard perl/lib/NeedRestart/UI/*.pm) xgettext -o $@ --msgid-bugs-address=thomas@fiasko-nw.net \ --from-code=UTF-8 \ --package-name=needrestart --package-version=2.12 \ --keyword --keyword='$$__' --keyword=__ --keyword=__x \ --keyword=__n:1,2 --keyword=__nx:1,2 --keyword=__xn \ --keyword=N__ --language=perl $^ po/needrestart-notify/messages.pot: ex/notify.d/*-* xgettext -o $@ --msgid-bugs-address=thomas@fiasko-nw.net \ --package-name=needrestart-notify --package-version=2.12 \ --language=shell $^ mo-files: $(MAKE) -C po/needrestart $(MAKE) -C po/needrestart-notify needrestart-3.1/NEWS000066400000000000000000000057461325725522600144210ustar00rootroot00000000000000Changes in 2.12 =============== docker containers ----------------- Needrestart ignores processes within docker containers since there are no pending library updates within containers by design. Needrestart still detects docker containers to mitigate false positives. More information: README.Cont.md non-interactive runs -------------------- If needrestart is configured to run in interactive mode but is run non-interactive (i.e. unattended-upgrades) it will fallback to list only mode. Changes in 2.1 ============== containers (LXC et. al.) ------------------------ Needrestart tries to detect if a process runs inside a container like LXC or docker. There are special scanner packages (NeedRestart::CONT::*) which implements the implementation specific detection and restarting. More information: README.Cont.md Changes in 0.8 ============== interpreters (Perl et. al.) --------------------------- Needrestart tries to detect if interpreters are using old source files. There are special scanner packages (NeedRestart::Interp::*) which implements the interpreter specific detection. Since most interpreter languages allow dynamic source code loading (eval) and we are using a home made source parcing there is a reasonable possibility to miss outdated source files. More information: README.Interp.md kernel upgrades --------------- Needrestart tries to detect if an pending kernel upgrade is available. It will only suggest a reboot. More information: README.Kernel.md UI -- The UI implementation NeedRestart::UI::Dialog has been dropped. Changes in 0.6 ============== systemd support --------------- If needrestart detects a running systemd it is used as primary source to identify service names. This speedups the detection significantly. The traditional detection using package managers is still used if systemd is not running or systemctl does not return a service name for a PID. Changes in 0.3 ============== blacklisting ------------ It might be a bad idea to (auto) restart certain daemons. Therefor a new config option is available to ignore binaries by matching a regex. The supplied default configuration ignores dbus, NetworkManager and various display managers. user interface -------------- The old basic user interface has been replace by a modular approach. User interfaces are now implemented in the NeedRestart::UI::* packages. New UI packages can be added by putting them into perl's search path. Using Module::Find to load any NeedRestart::UI::* package. Packages failing to load are ignored. The following UI implementations are shipped: * NeedRestart::UI::Debconf - use Debian's debconf front end * NeedRestart::UI::Dialog - use UI::Dialog * NeedRestart::UI::stdio - the simple old UI sophisticated apt/dpkg trigger ------------------------------ The new apt/dpkg trigger only runs needrestart if there was a package unpacked by dpkg and no error has occurred during the dpkg run. The scripts and config files required for the apt and dpkg integration are installed by default. needrestart-3.1/README.Cont.md000066400000000000000000000017701325725522600160740ustar00rootroot00000000000000needrestart - container support =============================== If needrestart has found a process using obsolete binaries it checks if the process is part of a container. If the process is part of a container it might not be possible to restart it using Sys-V/systemd. There are special packages (NeedRestart::CONT::*) implementing the container detection and restarting. NeedRestart::CONT::docker ------------------------- Recognized by: cgroup path (`/system.slice/docker-*.scope` || `/docker/*`) Docker containers are ignored (needrestart 2.12+) since there are no updates within docker containers by design. NeedRestart::CONT::LXC ---------------------- Recognized by: cgroup path (`/lxc/*`) For each container which should be restarted needrestart calls `lxc-stop --reboot --name $NAME`. NeedRestart::CONT::machined --------------------------- Recognized by: cgroup path (`/machine.slice/machine-*.scope`) For each container which should be restarted needrestart calls `machinectl reboot $NAME`. needrestart-3.1/README.Interp.md000066400000000000000000000042111325725522600164230ustar00rootroot00000000000000needrestart - interpreter support ================================= Needrestart checks running processes for using obsolete binaries. If no obsolete binary was found needrestart scans for known interpreters. There are special packages (NeedRestart::Interp::*) implementing the source code file list extraction. The executable (/proc//exec) is used to detect the running interpreter. Whenever source files where located their ctime values are retrieved. If any of the source files has been changed after process creation time a restart of the pid is triggered. This is no perfect valuation since there are no inode information like for loaded binary objects nor has needrestart any chance to get a verified list of sourced files.. NeedRestart::Interp::Java ------------------------- Recognized binaries: /.+/bin/java Find source file by: n/a Try to detected loaded \.(class|jar) files by looking at open files. This approach will not reliably detect loaded java files. Finding the original command used to launch a java program is not that easy. Since there is no shebang we will not find any data about the original command in /proc/$PID. Running on systemd will allow us to find the service name due to the cgroup name - seems to work for java daemons like tomcat6. NeedRestart::Interp::Perl ------------------------- Recognized binaries: /usr/(local/)?bin/perl Find source file by: command line interpretation We are using `Module::ScanDeps` to find used packages. This should work on any static loaded packages, dynamic stuff will fail. NeedRestart::Interp::Python --------------------------- Recognized binaries: /usr/(local/)?bin/python.* Find source file by: command line interpretation The source file is scanned for 'import' and 'from' lines. All paths in `sys.path` are scanned for the module files. This should work on any static loaded modules. NeedRestart::Interp::Ruby ------------------------- Recognized binaries: /usr/(local/)?bin/ruby.* Find source file by: command line interpretation The source file is scanned for 'load' and 'require' lines. All paths in `$:` are scanned for the module files. This should work on any static loaded modules. needrestart-3.1/README.batch.md000066400000000000000000000015041325725522600162450ustar00rootroot00000000000000needrestart - batch mode ======================== Needrestart can be run in batch mode: ```console # needrestart -b NEEDRESTART-VER: 2.1 NEEDRESTART-KCUR: 3.19.3-tl1+ NEEDRESTART-KEXP: 3.19.3-tl1+ NEEDRESTART-KSTA: 1 NEEDRESTART-SVC: systemd-journald.service NEEDRESTART-SVC: systemd-machined.service NEEDRESTART-CONT: LXC web1 ``` Batch mode can be used to use the results of needrestart in other scripts. While needrestart is run in batch mode it will never show any UI dialogs nor restart anything. The output format is complient to the *apt-dater protocol*[1]. [1] https://github.com/DE-IBH/apt-dater-host/blob/master/doc/ The kernel status (`NEEDRESTART-KSTA`) value has the following meaning: - *0*: unknown or failed to detect - *1*: no pending upgrade - *2*: ABI compatible upgrade pending - *3*: version upgrade pending needrestart-3.1/README.md000066400000000000000000000055441325725522600151750ustar00rootroot00000000000000needrestart =========== About ----- *needrestart* checks which daemons need to be restarted after library upgrades. It is inspired by *checkrestart* from the *debian-goodies* package. There are some hook scripts in the ``ex/`` directory (to be used with *apt* and *dpkg*. The scripts will call *needrestart* after any package installation/upgrades. *needrestart* should work on GNU/Linux. It has limited functionality on GNU/kFreeBSD since `/proc//maps` does not show removed file links. Restarting Services ------------------- *needrestart* supports but does not require systemd (available since v0.6). If systemd is used you should use libpam-systemd, too. If needrestart detects systemd it will assume that libpam-systemd is used and relies on cgroup names to detect if a process belongs to a user session or a daemon. If you do not use libpam-systemd you should set $nrconf{has_pam_systemd} to 0 within needrestart.conf. If systemd is not available or does not return a service name *needrestart* uses hooks to identify the corresponding System V init script. The shipped hooks support the following package managers: * *dpkg* * *rpm* * *pacman* The *service* command is used to run the tradiditional System V init script. Frontends --------- *needrestart* uses a modular aproach based on perl packages providing the user interface. The following frontends are shipped: * *NeedRestart::UI::Debconf* using *debconf* * *NeedRestart::UI::stdio* fallback using stdio interaction Kernel & Microcode ------------------ *needrestart* 0.8 brings a obsolete kernel detection feature. In *needrestart* 3.0 a [processor microcode update detection feature](README.uCode.md) for Intel CPUs has been added. Interpreters ------------ *needrestart* 0.8 brings an [interpreter scanning feature](README.Interp.md). Interpreters not only map binary (shared) objects but also use plaintext source files. The interpreter detection tries to check for outdated source files since they may contain security issues, too. This is only a heuristic and might fail to detect all relevant source files. The following interpreter scanners are shipped: * *NeedRestart::Interp::Java* * *NeedRestart::Interp::Perl* * *NeedRestart::Interp::Python* * *NeedRestart::Interp::Ruby* Containers ---------- *needrestart* 2.1 [detects some container technologies](README.Cont.md). If a process is part of a container it might not be possible to restart it using Sys-V/systemd. There are special perl packages (NeedRestart::CONT::*) implementing the container detection and restarting. The following container detectors are shipped: * *NeedRestart::CONT::docker* * *NeedRestart::CONT::LXC* * *NeedRestart::CONT::machined* Batch Mode ---------- *needrestart* can be run in [batch mode](README.batch.md) to use the results within other programs or scripts. There is also a [nagios plugin mode](README.nagios.md) available. needrestart-3.1/README.nagios.md000066400000000000000000000014211325725522600164420ustar00rootroot00000000000000needrestart - nagios plugin mode ================================ Needrestart can be used as a nagios plugin: ```console # needrestart -p CRIT - Kernel: 4.6.0-1-amd64, Services: 1 (!), Containers: none, Sessions: 2 (!)|Kernel=0;0;;0;2 Services=1;;0;0 Containers=0;;0;0 Sessions=2;0;;0 Services: - NetworkManager.service Sessions: - thomas @ session #16 - thomas @ user manager service ``` Since needrestart requires root privileges to scan processes of other users you should use sudo. Needrestart ships some example files to run needrestart as nagios plugin using sudo: - `ex/nagios/check_needrestart` - calls sudo to invoke needrestart - `ex/nagios/needrestart-nagios` - sudo(8) config allowing nagios to run needrestart as root - `ex/nagios/plugin.conf` - nagios(8) integration needrestart-3.1/README.uCode.md000066400000000000000000000011371325725522600162250ustar00rootroot00000000000000needrestart - microcode support =============================== Some CPU architectures supports microcode updates to mitigate hardware-level bugs. Needrestart checks if the current running microcode signature matches the most recent version available on the host. The detection is currently only supported for Intel CPUs. Intel ----- Needrestart uses `iucode-tool`[1] to test for pending microcode updates. On Debian GNU/Linux it should be sufficient to install the `intel-microcode` package: ```console # apt-get install intel-microcode ``` [1] https://gitlab.com/iucode-tool/iucode-tool/wikis/home needrestart-3.1/ex/000077500000000000000000000000001325725522600143225ustar00rootroot00000000000000needrestart-3.1/ex/99needrestart000066400000000000000000000005511325725522600167500ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Call needrestart after package upgrades/installations and check # for pending service restarts. This is a quite simple approach, # a more sophisticated approach can be found in the $SOURCES/ex/apt/ # directory. # DPkg::Post-Invoke {"test -x /usr/sbin/needrestart && /usr/sbin/needrestart || true"; }; needrestart-3.1/ex/apt/000077500000000000000000000000001325725522600151065ustar00rootroot00000000000000needrestart-3.1/ex/apt/apt-pinvoke000077500000000000000000000016701325725522600172750ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # RUNDIR=/run/needrestart # dpkg had an error... exit (silently) if [ -e "$RUNDIR/errored" ]; then [ -e "$RUNDIR/unpacked" ] && echo "needrestart is being skipped since dpkg has failed" rm -f "$RUNDIR/errored" exit 0 fi if [ -e "$RUNDIR/unpacked" ]; then if [ -n "$NEEDRESTART_SUSPEND" ]; then echo "packages have been installed but needrestart is suspended" exit 0 fi rm -f "$RUNDIR/unpacked" exec /usr/sbin/needrestart "$@" fi needrestart-3.1/ex/apt/dpkg-status000077500000000000000000000016071325725522600173060ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # RUNDIR=/run/needrestart mkdir -p "$RUNDIR" touched=0 errored=0 while read tag p0 p1 p2 p3 p4 pp; do if [ "$tag" = 'status:' -a "$p1" = 'unpacked' ]; then if [ "$touched" = 0 ]; then touch "$RUNDIR/unpacked" touched=1 fi else if [ "$tag" = 'status:' -a "$p1" = ':' -a "$p2" = 'error' -a "$p3" = ':' ]; then if [ "$errored" = 0 ]; then touch "$RUNDIR/errored" errored=1 fi fi fi done needrestart-3.1/ex/apt/needrestart-apt_d000066400000000000000000000005221325725522600204350ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Call needrestart after package upgrades/installations and check # for pending service restarts. Should only be triggered if there # was no error during installation. # DPkg::Post-Invoke {"test -x /usr/lib/needrestart/apt-pinvoke && /usr/lib/needrestart/apt-pinvoke || true"; }; needrestart-3.1/ex/apt/needrestart-dpkg_d000066400000000000000000000004221325725522600205750ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Scan for (successfully) installed packages, # triggers needrestart in apt's Dpkg::Post-Invoke # hook. status-logger=(test -x /usr/lib/needrestart/dpkg-status && /usr/lib/needrestart/dpkg-status || cat > /dev/null) needrestart-3.1/ex/conf.d/000077500000000000000000000000001325725522600154715ustar00rootroot00000000000000needrestart-3.1/ex/conf.d/README.needrestart000066400000000000000000000003611325725522600206700ustar00rootroot00000000000000Files ending with .conf and located in the /etc/needrestart/conf.d directory are parsed by needrestart's default configuration file. Files are parsed in order (using Perl's sort sub) and override or modify any previously set config option. needrestart-3.1/ex/debconf/000077500000000000000000000000001325725522600157225ustar00rootroot00000000000000needrestart-3.1/ex/debconf/needrestart.templates000066400000000000000000000035201325725522600221620ustar00rootroot00000000000000Template: needrestart/ui-query_pkgs_title Type: title _Description: Daemons using outdated libraries Template: needrestart/ui-query_pkgs Type: multiselect Choices: ${PKGS} _Description: Which services should be restarted? Template: needrestart/ui-kernel_announce_abi Type: note _Description: Newer kernel available The currently running kernel version is ${KVERSION} and there is an ABI compatible upgrade pending. . Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. Template: needrestart/ui-kernel_announce_ver Type: note _Description: Newer kernel available The currently running kernel version is ${KVERSION} which is not the expected kernel version ${EVERSION}. . Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. Template: needrestart/ui-kernel_title Type: title _Description: Pending kernel upgrade Template: needrestart/ui-ehint_title Type: title _Description: Restart pending... Template: needrestart/ui-ehint_announce Type: note _Description: This system runs ${EHINT} - you should consider rebooting! For more details, run «needrestart -m a». Template: needrestart/ui-ucode_title Type: title _Description: Outdated processor microcode Template: needrestart/ui-ucode_announce Type: note _Description: Processor microcode update The currently running processor microcode revision is ${CURRENT} which is not the expected microcode revision ${AVAIL}. . Restarting the system to load the new processor microcode will not be handled automatically, so you should consider rebooting. Template: needrestart/ui-query_conts_title Type: title _Description: Containers using outdated libraries Template: needrestart/ui-query_conts Type: multiselect Choices: ${CONTS} _Description: Which containers should be restarted? needrestart-3.1/ex/debconf/po/000077500000000000000000000000001325725522600163405ustar00rootroot00000000000000needrestart-3.1/ex/debconf/po/POTFILES.in000066400000000000000000000001021325725522600201060ustar00rootroot00000000000000[encoding: UTF-8] [type: gettext/rfc822deb] needrestart.templates needrestart-3.1/ex/debconf/po/de.po000066400000000000000000000076251325725522600173020ustar00rootroot00000000000000# German debconf translation for the needrestart package. # Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the needrestart package. # Thomas Liske , 2014. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: needrestart 2.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-03-29 13:45+0200\n" "PO-Revision-Date: 2016-05-15 15:17+0100\n" "Last-Translator: Thomas Liske \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. Type: title #. Description #: ../needrestart.templates:1001 msgid "Daemons using outdated libraries" msgstr "Dienste, die veraltete Bibliotheken nutzen" #. Type: multiselect #. Description #: ../needrestart.templates:2001 msgid "Which services should be restarted?" msgstr "Welche Dienste sollen neu gestartet werden?" #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "Newer kernel available" msgstr "Neuer Kernel vorhanden" #. Type: note #. Description #: ../needrestart.templates:3001 msgid "" "The currently running kernel version is ${KVERSION} and there is an ABI " "compatible upgrade pending." msgstr "" "Für die aktuelle Kernel-Version ${KVERSION} ist ein ABI-kompatibles Update " "vorhanden." #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "" "Restarting the system to load the new kernel will not be handled " "automatically, so you should consider rebooting." msgstr "" "Das System wird nicht automatisch neu gestartet, um den neuen Kernel zu " "laden. Ein Neustart sollte durchgeführt werden." #. Type: note #. Description #: ../needrestart.templates:4001 msgid "" "The currently running kernel version is ${KVERSION} which is not the " "expected kernel version ${EVERSION}." msgstr "" "Die aktuelle Kernel-Version ist ${KVERSION}, es wird jedoch die Version " "${EVERSION} erwartet." #. Type: title #. Description #: ../needrestart.templates:5001 msgid "Pending kernel upgrade" msgstr "Ausstehendes Kernel-Upgrade" #. Type: title #. Description #: ../needrestart.templates:6001 msgid "Restart pending..." msgstr "Ausstehender Neustart..." #. Type: note #. Description #: ../needrestart.templates:7001 msgid "This system runs ${EHINT} - you should consider rebooting!" msgstr "" "Das System verwendet ${EHINT} - ein Neustart sollte durchgeführt werden." #. Type: note #. Description #: ../needrestart.templates:7001 msgid "For more details, run «needrestart -m a»." msgstr "Der Befehl »needrestart -m a« zeigt mehr Details." #. Type: title #. Description #: ../needrestart.templates:8001 msgid "Outdated processor microcode" msgstr "Veralteter Prozessor Mikrocode" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "Processor microcode update" msgstr "Prozessor Mikrocode-Update" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "" "The currently running processor microcode revision is ${CURRENT} which is " "not the expected microcode revision ${AVAIL}." msgstr "" "Die laufende Prozessor Mikrocode-Revision ist ${CURRENT}, es wird jedoch die " "Revision ${AVAIL} erwaret." #. Type: note #. Description #: ../needrestart.templates:9001 msgid "" "Restarting the system to load the new processor microcode will not be " "handled automatically, so you should consider rebooting." msgstr "" "Das System wird nicht automatisch neu gestartet, um den neuen Prozessor " "Mikrocode zu laden. Ein Neustart sollte durchgeführt werden." #. Type: title #. Description #: ../needrestart.templates:10001 msgid "Containers using outdated libraries" msgstr "Container, die veraltete Bibliotheken nutzen" #. Type: multiselect #. Description #: ../needrestart.templates:11001 msgid "Which containers should be restarted?" msgstr "Welche Container sollen neu gestartet werden?" needrestart-3.1/ex/debconf/po/ru.po000066400000000000000000000065401325725522600173330ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-05-15 12:21+0200\n" "PO-Revision-Date: 2016-06-11 10:32+0300\n" "Last-Translator: Vladimir Kudrya \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.8\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #. Type: title #. Description #: ../needrestart.templates:1001 msgid "Daemons using outdated libraries" msgstr "Демоны, использующие устаревшие библиотеки" #. Type: multiselect #. Description #: ../needrestart.templates:2001 msgid "Which services should be restarted?" msgstr "Какие службы должны быть перезапущены?" #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "Newer kernel available" msgstr "Доступно новое ядро" #. Type: note #. Description #: ../needrestart.templates:3001 msgid "" "The currently running kernel version is ${KVERSION} and there is an ABI " "compatible upgrade pending." msgstr "" "Версия текущего ядра: ${KVERSION}, имеется незаконченное обновление, " "несовместимое на уровне ABI." #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "" "Restarting the system to load the new kernel will not be handled " "automatically, so you should consider rebooting." msgstr "" "Перезапуск системы для загрузки нового ядра не производится автоматически, " "поэтому запланируйте перезагрузку." #. Type: note #. Description #: ../needrestart.templates:4001 msgid "" "The currently running kernel version is ${KVERSION} which is not the " "expected kernel version ${EVERSION}." msgstr "" "Версия текущего ядра: ${KVERSION}, что отлично от ожидаемой версии " "${EVERSION}." #. Type: title #. Description #: ../needrestart.templates:5001 msgid "Pending kernel upgrade" msgstr "Ожидается обновление ядра" #. Type: title #. Description #: ../needrestart.templates:6001 msgid "Restart pending..." msgstr "Ожидается перезапуск..." #. Type: note #. Description #: ../needrestart.templates:7001 msgid "This system runs ${EHINT} - you should consider rebooting!" msgstr "Эта система использует ${EHINT} - запланируйте перезагрузку!" #. Type: note #. Description #: ../needrestart.templates:7001 msgid "For more details, run «needrestart -m a»." msgstr "Для получения подробностей выполните «needrestart -m a»." #. Type: title #. Description #: ../needrestart.templates:8001 msgid "Containers using outdated libraries" msgstr "Контейнеры, использующие устаревшие библиотеки" #. Type: multiselect #. Description #: ../needrestart.templates:9001 msgid "Which containers should be restarted?" msgstr "Какие контейнеры должны быть перезапущены?" needrestart-3.1/ex/debconf/po/templates.pot000066400000000000000000000056431325725522600210720ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-03-29 13:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. Type: title #. Description #: ../needrestart.templates:1001 msgid "Daemons using outdated libraries" msgstr "" #. Type: multiselect #. Description #: ../needrestart.templates:2001 msgid "Which services should be restarted?" msgstr "" #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "Newer kernel available" msgstr "" #. Type: note #. Description #: ../needrestart.templates:3001 msgid "" "The currently running kernel version is ${KVERSION} and there is an ABI " "compatible upgrade pending." msgstr "" #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "" "Restarting the system to load the new kernel will not be handled " "automatically, so you should consider rebooting." msgstr "" #. Type: note #. Description #: ../needrestart.templates:4001 msgid "" "The currently running kernel version is ${KVERSION} which is not the " "expected kernel version ${EVERSION}." msgstr "" #. Type: title #. Description #: ../needrestart.templates:5001 msgid "Pending kernel upgrade" msgstr "" #. Type: title #. Description #: ../needrestart.templates:6001 msgid "Restart pending..." msgstr "" #. Type: note #. Description #: ../needrestart.templates:7001 msgid "This system runs ${EHINT} - you should consider rebooting!" msgstr "" #. Type: note #. Description #: ../needrestart.templates:7001 msgid "For more details, run «needrestart -m a»." msgstr "" #. Type: title #. Description #: ../needrestart.templates:8001 msgid "Outdated processor microcode" msgstr "" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "Processor microcode update" msgstr "" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "" "The currently running processor microcode revision is ${CURRENT} which is " "not the expected microcode revision ${AVAIL}." msgstr "" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "" "Restarting the system to load the new processor microcode will not be " "handled automatically, so you should consider rebooting." msgstr "" #. Type: title #. Description #: ../needrestart.templates:10001 msgid "Containers using outdated libraries" msgstr "" #. Type: multiselect #. Description #: ../needrestart.templates:11001 msgid "Which containers should be restarted?" msgstr "" needrestart-3.1/ex/nagios/000077500000000000000000000000001325725522600156025ustar00rootroot00000000000000needrestart-3.1/ex/nagios/check_needrestart000077500000000000000000000010071325725522600212030ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # exec sudo -n -- /usr/sbin/needrestart -p needrestart-3.1/ex/nagios/needrestart-nagios000066400000000000000000000004241325725522600213230ustar00rootroot00000000000000# needrestart nagios plugin sudoers.d config file # ----------------------------------------------- # # Please consider a look at /etc/sudoers.d/README howto enable this file. # # Allow nagios to execute the needrestart command nagios ALL=NOPASSWD: /usr/sbin/needrestart -p needrestart-3.1/ex/nagios/plugin.conf000066400000000000000000000005671325725522600177570ustar00rootroot00000000000000## remember: check_needrestart is a local check only define command { command_name check_needrestart command_line /usr/lib/nagios/plugins/check_needrestart } ## example service #define service { # host_name localhost # service_description NEEDRESTART # check_command check_needrestart # use generic-service #} needrestart-3.1/ex/needrestart.conf000066400000000000000000000133711325725522600175160ustar00rootroot00000000000000 # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This is the configuration file of needrestart. This is perl syntax. # needrstart uses reasonable default values, you might not need to # change anything. # Verbosity: # 0 => quiet # 1 => normal (default) # 2 => verbose #$nrconf{verbosity} = 2; # Path of the package manager hook scripts. #$nrconf{hook_d} = '/etc/needrestart/hook.d'; # Path of user notification scripts. #$nrconf{notify_d} = '/etc/needrestart/notify.d'; # Path of restart scripts. #$nrconf{restart_d} = '/etc/needrestart/restart.d'; # Disable sending notifications to user sessions running obsolete binaries # using scripts from $nrconf{notify_d}. #$nrconf{sendnotify} = 0; # If needrestart detects systemd it assumes that you use systemd's pam module. # This allows needrestart to easily detect user session. In case you use # systemd *without* pam_systemd.so you should set has_pam_systemd to false # to enable legacy session detection! #$nrconf{has_pam_systemd} = 0; # Restart mode: (l)ist only, (i)nteractive or (a)utomatically. # # ATTENTION: If needrestart is configured to run in interactive mode but is run # non-interactive (i.e. unattended-upgrades) it will fallback to list only mode. # #$nrconf{restart} = 'i'; # Use preferred UI package. #$nrconf{ui} = 'NeedRestart::UI::stdio'; # Change default answer to 'no' in (i)nteractive mode. #$nrconf{defno} = 1; # Set UI mode to (e)asy or (a)dvanced. #$nrconf{ui_mode} = 'e'; # Print a combined `systemctl restart` command line for skipped services. #$nrconf{systemctl_combine} = 1; # Blacklist binaries (list of regex). $nrconf{blacklist} = [ # ignore sudo (not a daemon) qr(^/usr/bin/sudo(\.dpkg-new)?$), # ignore DHCP clients qr(^/sbin/(dhclient|dhcpcd5|pump|udhcpc)(\.dpkg-new)?$), # ignore apt-get (Debian Bug#784237) qr(^/usr/bin/apt-get(\.dpkg-new)?$), ]; # Blacklist services (list of regex) - USE WITH CARE. # You should prefere to put services to $nrconf{override_rc} instead. # Any service listed in $nrconf{blacklist_rc} we be ignored completely! #$nrconf{blacklist_rc} = [ #]; # Override service default selection (hash of regex). $nrconf{override_rc} = { # DBus qr(^dbus) => 0, # display managers qr(^gdm) => 0, qr(^kdm) => 0, qr(^nodm) => 0, qr(^sddm) => 0, qr(^wdm) => 0, qr(^xdm) => 0, qr(^lightdm) => 0, qr(^slim) => 0, qr(^lxdm) => 0, # networking stuff qr(^bird) => 0, qr(^network-manager) => 0, qr(^NetworkManager) => 0, qr(^wpa_supplicant) => 0, qr(^openvpn) => 0, qr(^quagga) => 0, qr(^tinc) => 0, qr(^(open|free|libre|strong)swan) => 0, # gettys qr(^getty@.+\.service) => 0, # systemd --user qr(^user@\d+\.service) => 0, # misc qr(^zfs-fuse) => 0, qr(^mythtv-backend) => 0, qr(^xendomains) => 0, qr(^lxcfs) => 0, qr(^libvirt) => 0, qr(^docker) => 0, # workaround for broken systemd-journald # (see also Debian Bug#771122 & #771254) qr(^systemd-journald) => 0, # more systemd stuff # (see also Debian Bug#784238 & #784437) qr(^emergency\.service$) => 0, qr(^rescue\.service$) => 0, # do not restart oneshot services, see #862840 qr(^apt-daily\.service$) => 0, qr(^apt-daily-upgrade\.service$) => 0, qr(^unattended-upgrades\.service$) => 0, # ignore rc-local.service, see #852864 qr(^rc-local\.service$) => 0, # don't restart systemd-logind, see #798097 qr(^systemd-logind) => 0, }; # Override container default selection (hash of regex). $nrconf{override_cont} = { }; # Disable interpreter scanners. #$nrconf{interpscan} = 0; # Ignore script files matching these regexs: $nrconf{blacklist_interp} = [ # ignore temporary files qr(^/tmp/), qr(^/var/), qr(^/run/), ]; # Ignore +x mapped files matching one of these regexs: $nrconf{blacklist_mappings} = [ # special device paths qr(^/(SYSV00000000( \(deleted\))?|drm(\s|$)|dev/)), # aio(7) mapping qr(^/\[aio\]), # Oil Runtime Compiler's JIT files qr#/orcexec\.[\w\d]+( \(deleted\))?$#, # plasmashell (issue #65) qr(/#\d+( \(deleted\))?$), # Java Native Access qr#/tmp/jna--#, # Java Foreign Function Interface qr#^/tmp/jffi#, ]; # Verify mapped files in fileystem: # 0 : enabled (default) # -1: ignore non-existing files, workaround for broken grsecurity kernels # 1 : disable check completely, rely on content of maps file only $nrconf{skip_mapfiles} = (-d '/proc/sys/kernel/grsecurity' ? -1 : 0); # Enable/disable hints on pending kernel upgrades: # 1: requires the user to acknowledge pending kernels # 0: disable kernel checks completely # -1: print kernel hints to stderr only #$nrconf{kernelhints} = -1; # Nagios Plugin: configure return code use by nagios # as service status[1]. # # [1] https://nagios-plugins.org/doc/guidelines.html#AEN78 # # Default: # 'nagios-status' => { # 'sessions' => 1, # 'services' => 2, # 'kernel' => 2, # 'ucode' => 2, # 'containers' => 1 # }, # # Example: to ignore outdated sessions (status OK) # $nrconf{'nagios-status'}->{sessions} = 0; # Read additional config snippets. if(-d q(/etc/needrestart/conf.d)) { foreach my $fn (sort ) { print STDERR "$LOGPREF eval $fn\n" if($nrconf{verbose}); eval do { local(@ARGV, $/) = $fn; <>}; die "Error parsing $fn: $@" if($@); } } needrestart-3.1/ex/notify.conf000066400000000000000000000016711325725522600165060ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Configure notification globals (shell syntax) # Disable write to tty (notify.d/200-write) #NR_NOTIFYD_DISABLE_WRITE='1' # Disable needrestart-session (notify.d/300-needrestart-session) #NR_NOTIFYD_DISABLE_NEEDRESTART_SESSION='1' # Disable libnotify (notify.d/400-notify-send) #NR_NOTIFYD_DISABLE_NOTIFY_SEND='1' # Disable mail to user (notify.d/600-mail) NR_NOTIFYD_DISABLE_MAIL='1' # Where to find the shell function library from gettext-base #GETTEXTLIB='/usr/bin/gettext.sh' needrestart-3.1/ex/notify.d/000077500000000000000000000000001325725522600160545ustar00rootroot00000000000000needrestart-3.1/ex/notify.d/200-write000077500000000000000000000021041325725522600174300ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Use write to notify users on TTYs. . /usr/lib/needrestart/notify.d.sh if [ "$NR_NOTIFYD_DISABLE_WRITE" = '1' ]; then echo "[$0] disabled in global config" 1>&2 exit 1 fi case "$NR_SESSION" in /dev/tty*|/dev/pts*) echo "[$0] notify user $NR_USERNAME on $NR_SESSION" 1>&2 { echo gettext 'Your session is running obsolete binaries or libraries as listed below. Please consider a relogin or restart of the affected processes!' echo echo cat -n echo } | write "$NR_USERNAME" "$NR_SESSION" 2> /dev/null ;; *) echo "[$0] skip session w/o tty" 1>&2 exit 1 ;; esac needrestart-3.1/ex/notify.d/400-notify-send000077500000000000000000000031051325725522600205410ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Use notify-send (from libnotify-bin) to notify a user session via dbus. NSEND='/usr/bin/notify-send' test -x "$NSEND" || exit 1 . /usr/lib/needrestart/notify.d.sh if [ "$NR_NOTIFYD_DISABLE_NOTIFY_SEND" = '1' ]; then echo "[$0] disabled in global config" 1>&2 exit 1 fi case "$NR_SESSION" in session*) # cleanup environment unset DBUS_SESSION_BUS_ADDRESS export DISPLAY=$(sed -z -n s/^DISPLAY=//p "/proc/$NR_SESSPPID/environ") export XAUTHORITY=$(sed -z -n s/^XAUTHORITY=//p "/proc/$NR_SESSPPID/environ") if [ -z "$DISPLAY" ]; then echo "[$0] could not find DISPLAY for $NR_USERNAME on $NR_SESSION" 1>&2 exit 1 fi echo "[$0] notify user $NR_USERNAME on $DISPLAY" 1>&2 MSGTITLE=$(gettext 'Relogin or restarts required!') MSGBODY=$(gettext 'Your session is running obsolete binaries or libraries as listed below. Please consider a relogin or restart of the affected processes!')'\n'$(cat) su -p -s /bin/sh -c "$NSEND -u critical -i dialog-warning \"$MSGTITLE\" \"$MSGBODY\"" "$NR_USERNAME" ;; *) echo "[$0] skip session '$NR_SESSION'" 1>&2 exit 1; ;; esac needrestart-3.1/ex/notify.d/600-mail000077500000000000000000000025171325725522600172340ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Use /usr/bin/mail to notify a user via e-mail. MAILX='/usr/bin/mail' test -x "$MAILX" || exit 1 . /usr/lib/needrestart/notify.d.sh if [ "$NR_NOTIFYD_DISABLE_MAIL" = '1' ]; then echo "[$0] disabled in global config" 1>&2 exit 1 fi # Skip system users NR_USERID=`id -u "$NR_USERNAME"` if [ "0$NR_USERID" -gt 0 -a "0$NR_USERID" -lt 1000 ]; then echo "[$0] do not notify system-user $NR_USERNAME via mail" 1>&2 exit 1 fi echo "[$0] notify user $NR_USERNAME on $NR_SESSION via mail" 1>&2 { _NR_FQDN=$(hostname -f) eval_gettext 'Your session on host $_NR_FQDN ($NR_SESSION) is running obsolete binaries or libraries as listed below.' echo echo gettext "Please consider a relogin or restart of the affected processes!" echo echo cat } | fold -s -w 72 | "$MAILX" -s "Relogin or restarts on host $(hostname) required!" "$NR_USERNAME" needrestart-3.1/ex/notify.d/README.needrestart000066400000000000000000000014201325725522600212500ustar00rootroot00000000000000Files located in /etc/needrestart/notify.d are used to notify running user sessions about usage of outdated libraries. needrestart runs any executable file (except *~, *.dpkg-*, *.ex) naturally sorted by the filename for each notification. If the result code is 0 than needrestart will stop to run the remaining notification binaries. The following environment variables are set: - NR_SESSION Session identifier (tty device node or systemd's session name). - NR_SESSPPID The first pid in the session detected by needrestart. - NR_UID User ID of the session owner. - NR_USERNAME Username of the session owner. The following file descriptors are used: - /dev/stdin The list of obsolete processes. - /dev/stdout Closed. - /dev/stderr Available in verbose mode (-v). needrestart-3.1/ex/polkit/000077500000000000000000000000001325725522600156245ustar00rootroot00000000000000needrestart-3.1/ex/polkit/net.fiasko-nw.needrestart.policy000066400000000000000000000013421325725522600240470ustar00rootroot00000000000000 Authentication is required to run needrestart as root view-refresh auth_admin auth_admin auth_admin /usr/sbin/needrestart true needrestart-3.1/ex/restart.d/000077500000000000000000000000001325725522600162305ustar00rootroot00000000000000needrestart-3.1/ex/restart.d/README.needrestart000066400000000000000000000010161325725522600214250ustar00rootroot00000000000000Files located in /etc/needrestart/restart.d are used for services requiring a special procedure for restarting instead of systemctl/service command. Needrestart uses executable files matching the complete service names. If the host uses systemd the service names have '.service' as a suffix (dbus vs. dbus.service). Needrestart uses the systemctl/service command if no executable file is available to override the default behavior. The environment variable NR_VERBOSE will be set to '1' if the executable should be verbose. needrestart-3.1/ex/restart.d/dbus.service000077500000000000000000000030351325725522600205530ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Restart dbus and affiliated services under systemd using a procedure # suggested by @Vladimir-csp in github issue #44. # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi # check if there is a Display Manager running STATE_DM=$(systemctl show display-manager --property=ActiveState) # prepare well-known list of services requiring restart after restarting D-Bus RESTART_CHK="NetworkManager.service" RESTART_SVC="systemd-logind.service systemd-journald.service" for svc in $RESTART_CHK; do if [ "$(systemctl show $svc --property=ActiveState)" = 'ActiveState=active' ]; then RESTART_SVC="$RESTART_SVC $svc" fi done # stop Display Manager if running if [ "$STATE_DM" = 'ActiveState=active' ]; then systemctl stop display-manager.service fi # restard D-Bus systemctl restart dbus.service # reexec systemd systemctl daemon-reexec # restart daemons that directly depend on D-Bus systemctl restart $RESTART_SVC # start Display Manager again if [ "$STATE_DM" = 'ActiveState=active' ]; then systemctl start display-manager.service fi needrestart-3.1/ex/restart.d/systemd-manager000077500000000000000000000011231325725522600212530ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi exec systemctl daemon-reexec needrestart-3.1/ex/restart.d/sysv-init000077500000000000000000000011051325725522600201200ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi exec telinit u needrestart-3.1/hooks/000077500000000000000000000000001325725522600150315ustar00rootroot00000000000000needrestart-3.1/hooks/10-dpkg000077500000000000000000000041211325725522600161200ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # This DPKG hook tries to find the run-level scripts of the package's binary # which has old libraries in use. Some logic is taken from the checkrestart # (part of the debian-goodies package) package by Matt Zimmerman , # Javier Fernandez-Sanguino et. al. use Getopt::Std; use strict; use warnings; system("type dpkg-query 1> /dev/null 2> /dev/null"); exit 0 if ($? != -1 && $? >> 8); our $opt_v; getopts('v'); sub fork_pipe(@) { my $pid = open(HPIPE, '-|'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { close(STDIN); close(STDERR) unless($opt_v); exec(@_); exit; } \*HPIPE } my $FN = shift || die "Usage: $0 \n"; my $psearch = fork_pipe(qw(dpkg-query --search), $FN); my @pkgs; while(<$psearch>) { chomp; next if(/^local diversion/); next unless(/:/); next unless(/(\S+): $FN$/); push(@pkgs, $1); } close($psearch); exit(0) unless($#pkgs > -1); foreach my $pkg (@pkgs) { print "PACKAGE|$pkg\n"; my $plist = fork_pipe(qw(dpkg-query --listfiles), $pkg); while(<$plist>) { print "RC|$1\n" if(m@^/etc/init.d/(.+)$@); } close($plist); } exit(1); needrestart-3.1/hooks/20-rpm000077500000000000000000000035751325725522600160060ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # This RPM hook tries to find the run-level scripts of the package's binary # which has old libraries in use. use Getopt::Std; use strict; use warnings; system("type rpm 1> /dev/null 2> /dev/null"); exit 0 if ($? != -1 && $? >> 8); our $opt_v; getopts('c:v'); sub fork_pipe(@) { my $pid = open(HPIPE, '-|'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { close(STDIN); close(STDERR) unless($opt_v); exec(@_); exit; } \*HPIPE } my $FN = shift || die "Usage: $0 \n"; my $psearch = fork_pipe(qw(rpm -q --file), $FN); my @pkgs; while(<$psearch>) { chomp; next if(/^file .+ is not owned by any package/); push(@pkgs, $_); } close($psearch); exit(0) unless($#pkgs > -1); foreach my $pkg (@pkgs) { print "PACKAGE|$pkg\n"; my $plist = fork_pipe(qw(rpm -q --filesbypkg), $pkg); while(<$plist>) { print "RC|$2\n" if(m@^\S+\s+/etc(/rc\.d)?/init\.d/(.+)$@); } close($plist); } exit(1); needrestart-3.1/hooks/30-pacman000077500000000000000000000034741325725522600164460ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # This PacMan hook tries to find the run-level scripts of the package's binary # which has old libraries in use. use Getopt::Std; use strict; use warnings; system("type pacman 1> /dev/null 2> /dev/null"); exit 0 if ($? != -1 && $? >> 8); our $opt_v; getopts('c:v'); sub fork_pipe(@) { my $pid = open(HPIPE, '-|'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { close(STDIN); close(STDERR) unless($opt_v); exec(@_); exit; } \*HPIPE } my $FN = shift || die "Usage: $0 \n"; my $psearch = fork_pipe(qw(pacman -Qqo), $FN); my @pkgs; while(<$psearch>) { chomp; push(@pkgs, $_); } close($psearch); exit(0) unless($#pkgs > -1); foreach my $pkg (@pkgs) { print "PACKAGE|$pkg\n"; my $plist = fork_pipe(qw(pacman -Qql), $pkg); while(<$plist>) { print "RC|$2\n" if(m@/etc(/rc\.d)?/init\.d/(.+)$@); } close($plist); } exit(1); needrestart-3.1/hooks/90-none000077500000000000000000000030661325725522600161510ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # This fallback hook tries the guess the rc script name from the binary name. # It might work with programs which are not installed via an (supported) # package manager like dpkg or rpm. use Getopt::Std; use strict; use warnings; our $opt_v; getopts('c:v'); sub check_rc($) { my $bn = shift; my $rc = "/etc/init.d/$bn"; return ($bn) if(-x $rc); return (); } my $FN = shift || die "Usage: $0 \n"; $FN =~ m@/(([^/]+)d?)$@; my @rc; push(@rc, check_rc($1)); push(@rc, check_rc($2)) if($1 ne $2); exit(0) unless($#rc > -1); foreach my $rc (@rc) { print "PACKAGE|$rc\n"; print "RC|$rc\n"; } exit(1); needrestart-3.1/lib/000077500000000000000000000000001325725522600144545ustar00rootroot00000000000000needrestart-3.1/lib/iucode-scan-versions000077500000000000000000000036321325725522600204460ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # handle verbose mode if [ "$1" = "1" ]; then set -x fi # early boot initrd (required at least on Arch Linux) if type bsdtar > /dev/null 2>&1 ; then imgfiles="" for img in /boot/intel-ucode.img /boot/early_ucode.cpio ; do if [ -r "$img" ]; then imgfiles="$imgfiles $img" fi done if [ -n "$imgfiles" ]; then cat $imgfiles | bsdtar -Oxf /dev/stdin | iucode_tool -Sl -tb - 2>&1 exit $? fi fi # look for microcode updates in the filesystem IUCODE_TOOL_EXTRA_OPTIONS="" test -r /etc/default/intel-microcode && . /etc/default/intel-microcode # do not scan if adding Intel microcode to initrd is disabled test "$IUCODE_TOOL_INITRAMFS" = "no" && exit 0 # run iucode_tool to scan for microcodes if [ -r /usr/share/misc/intel-microcode* ]; then exec iucode_tool -Sl -tb /lib/firmware/intel-ucode -ta /usr/share/misc/intel-microcode* 2>&1 exit 1 fi exec iucode_tool -Sl $IUCODE_TOOL_EXTRA_OPTIONS -tb /lib/firmware/intel-ucode 2>&1 needrestart-3.1/lib/notify.d.sh000066400000000000000000000016311325725522600165430ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Shell library for scripts in /etc/needrestart/notify.d/ NOTIFYCONF='/etc/needrestart/notify.conf' GETTEXTLIB='/usr/bin/gettext.sh' export TEXTDOMAIN='needrestart-notify' if [ ! -r "$NOTIFYCONF" ]; then echo "[$0] Unable to read $NOTIFYCONF - aborting!" 1>&2 exit 1; fi # Load global config . "$NOTIFYCONF" # Load gettext shell library . "$GETTEXTLIB" # Get LANG of session export LANG=$(sed -z -n s/^LANG=//p "/proc/$NR_SESSPPID/environ") needrestart-3.1/lib/vmlinuz-get-version000077500000000000000000000035751325725522600203600ustar00rootroot00000000000000#!/bin/sh # ---------------------------------------------------------------------- # This file was taken from the Linux kernel source tree (scripts/extract-vmlinux) # and has been adopted for the use within needrestart. # # extract-vmlinux - Extract uncompressed vmlinux from a kernel image # # Inspired from extract-ikconfig # (c) 2009,2010 Dick Streefland # # (c) 2011 Corentin Chary # # Adopted for needrestart # (c) 2016 - 2017 Thomas Liske # # Licensed under the GNU General Public License, version 2 (GPLv2). # ---------------------------------------------------------------------- get_version() { # search and output version string pattern strings "$1" | grep -m 1 '^Linux version ' && exit 0 } try_decompress() { # The obscure use of the "tr" filter is to work around older versions of # "grep" that report the byte offset of the line instead of the pattern. # Try to find the header ($1) and decompress from here for pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"` do pos=${pos%%:*} tail -c+$pos "$img" | $3 > $tmp 2> /dev/null get_version $tmp done } # Check invocation: me=${0##*/} img=$1 if [ $# -lt 1 -o $# -gt 2 -o ! -s "$img" ] then echo "Usage: $me [debug]" >&2 exit 2 fi if [ "$2" = "1" ]; then set -x fi # Prepare temp files: tmp=$(mktemp) trap "rm -f $tmp" 0 # Initial attempt for uncompressed images or objects: get_version $img # That didn't work, so retry after decompression. which gunzip > /dev/null && try_decompress '\037\213\010' xy gunzip which unxz > /dev/null && try_decompress '\3757zXZ\000' abcde unxz which bunzip2 > /dev/null && try_decompress 'BZh' xy bunzip2 which unlzma > /dev/null && try_decompress '\135\0\0\0' xxx unlzma which lzop > /dev/null && try_decompress '\211\114\132' xy 'lzop -d' needrestart-3.1/man/000077500000000000000000000000001325725522600144615ustar00rootroot00000000000000needrestart-3.1/man/needrestart.1000066400000000000000000000044461325725522600170730ustar00rootroot00000000000000.TH NEEDRESTART "1" "January 2015" "needrestart " "User Commands" .SH NAME needrestart \- needrestart .SH DESCRIPTION needrestart checks which daemons need to be restarted after library upgrades. .SH USAGE Usage: .IP needrestart [\-(v|q)] [\-n] [\-c ] [\-r ] [\-f ] [\-u ] [\-(b|p)] [\-kl] .TP \fB\-v\fR be more verbose .TP \fB\-q\fR be quiet .TP \fB\-m\fR set level of technical details .TP e (e)asy mode .TP a (a)dvanced mode .TP \fB\-n\fR set default answer to 'no' .TP \fB\-c\fR config filename .TP \fB\-r\fR set restart mode .TP l (l)ist only .TP i (i)nteractive restart .TP a (a)utomatically restart .IP \fBATTENTION:\fR If needrestart is configured to run in interactive mode but is run non-interactive (i.e. unattended-upgrades) it will fallback to list only mode. .TP \fB\-b\fR enable batch mode .TP \fB\-p\fR nagios plugin mode: makes output and exit codes nagios compatible .TP \fB\-f\fR overwrite debconf(7) frontend, sets the DEBIAN_FRONT environment variable to .TP \fB\-u\fR use preferred UI package (-u ? shows available packages) .PP By using one of the following options only the specified checks are performed: .TP \fB\-k\fR check for obsolete kernel .TP \fB\-l\fR check for obsolete libraries .SH ENVIRONMENT The following environment variables can be used to override the config file options. Command line parameters do always supersede them. .TP \fBNEEDRESTART_MODE\fR Change the configured restart mode (see also the \fB\-r\fR parameter): (l)ist only, (i)nteractive or (a)utomatically .RE When used with apt-get(8) needrestart supports the following additional environment variables: .TP \fBDEBIAN_FRONT\fR The debconf(7) frontend to use, can also set using the \fB\-f\fR parameter. .TP \fBNEEDRESTART_SUSPEND\fR If set to a non-empty value the apt-get(8) hook will not run needrestart after installing or updating packages. .SH "AUTHOR" Thomas Liske .SH "COPYRIGHT" 2013 - 2018 (C) Thomas Liske [http://fiasko\-nw.net/~thomas/] .PP This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. .SH "UPSTREAM" https://github.com/liske/needrestart needrestart-3.1/needrestart000077500000000000000000001062211325725522600161560ustar00rootroot00000000000000#!/usr/bin/perl # nagios: -epn # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use Cwd qw(realpath); use Getopt::Std; use NeedRestart; use NeedRestart::UI; use NeedRestart::Interp; use NeedRestart::Kernel; use NeedRestart::uCode; use NeedRestart::Utils; use Sort::Naturally; use Locale::TextDomain 'needrestart'; use List::Util qw(sum); use warnings; use strict; $|++; $Getopt::Std::STANDARD_HELP_VERSION++; my $LOGPREF = '[main]'; my $is_systemd = -d qq(/run/systemd/system); my $is_tty = (-t *STDERR || -t *STDOUT || -t *STDIN); my $is_container; # check if we are inside of a container if (-r "/proc/1/environ") { local $/; open(HENV, '<', '/proc/1/environ'); $is_container = scalar(grep {/^container=/;} unpack("(Z*)*", )); close(HENV) } sub HELP_MESSAGE { print <] [-r ] [-f ] [-u ] [-bkl] -v be more verbose -q be quiet -m set detail level e (e)asy mode a (a)dvanced mode -n set default answer to 'no' -c config filename -r set restart mode l (l)ist only i (i)nteractive restart a (a)utomatically restart -b enable batch mode -p enable nagios plugin mode -f overwrite debconf frontend (DEBIAN_FRONTEND, debconf(7)) -u use preferred UI package (-u ? shows available packages) By using the following options only the specified checks are performed: -k check for obsolete kernel -l check for obsolete libraries -w check for obsolete CPU microcode --help show this help --version show version information USG } sub VERSION_MESSAGE { print < Copyright Holder: 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] Upstream: https://github.com/liske/needrestart This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. LIC #/ } our %nrconf = ( verbosity => 1, hook_d => '/etc/needrestart/hook.d', notify_d => '/etc/needrestart/notify.d', restart_d => '/etc/needrestart/restart.d', sendnotify => 1, restart => 'i', defno => 0, ui_mode => 'a', systemctl_combine => 0, blacklist => [], blacklist_interp => [], blacklist_rc => [], blacklist_mappings => [], override_rc => {}, override_cont => {}, skip_mapfiles => 0, interpscan => 1, kernelhints => 1, ucodehints => 1, q(nagios-status) => { services => 1, kernel => 2, ucode => 2, sessions => 2, containers => 1, }, has_pam_systemd => 1, ); # backup ARGV (required for Debconf) my @argv = @ARGV; our $opt_c = '/etc/needrestart/needrestart.conf'; our $opt_v; our $opt_r; our $opt_n; our $opt_m; our $opt_b; our $opt_f; our $opt_k; our $opt_l; our $opt_p; our $opt_q; our $opt_u; our $opt_w; unless(getopts('c:vr:nm:bf:klpqu:w')) { HELP_MESSAGE; exit 1; } # disable exiting and STDOUT in Getopt::Std for further use of getopts $Getopt::Std::STANDARD_HELP_VERSION = undef; # restore ARGV @ARGV = @argv; die "ERROR: Could not read config file '$opt_c'!\n" unless(-r $opt_c || $opt_b); # overwrite debconf frontend $ENV{DEBIAN_FRONTEND} = $opt_f if($opt_f); # be quiet if($opt_q) { $nrconf{verbosity} = 0; } # be verbose elsif($opt_v) { $nrconf{verbosity} = 2; } # slurp config file print STDERR "$LOGPREF eval $opt_c\n" if($nrconf{verbosity} > 1); eval do { local(@ARGV, $/) = $opt_c; <>}; die "Error parsing $opt_c: $@" if($@); # fallback to stdio on verbose mode $nrconf{ui} = qq(NeedRestart::UI::stdio) if($nrconf{verbosity} > 1); die "Hook directory '$nrconf{hook_d}' is invalid!\n" unless(-d $nrconf{hook_d} || $opt_b); $opt_r = $ENV{NEEDRESTART_MODE} if(!defined($opt_r) && exists($ENV{NEEDRESTART_MODE})); $opt_r = $nrconf{restart} unless(defined($opt_r)); die "ERROR: Unknown restart option '$opt_r'!\n" unless($opt_r =~ /^(l|i|a)$/); $is_tty = 0 if($opt_r eq 'i' && exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive'); $opt_r = 'l' if(!$is_tty && $opt_r eq 'i'); $opt_m = $nrconf{ui_mode} unless(defined($opt_m)); die "ERROR: Unknown UI mode '$opt_m'!\n" unless($opt_m =~ /^(e|a)$/); $opt_r = 'l' if($opt_m eq 'e'); $nrconf{defno}++ if($opt_n); $opt_b++ if($opt_p); # print version in verbose mode print STDERR "$LOGPREF needrestart v$NeedRestart::VERSION\n" if($nrconf{verbosity} > 1); # running mode (user or root) my $uid = $<; if($uid) { if($opt_p) { print "UNKN - This plugin needs to be run as root!\n"; exit 3; } print STDERR "$LOGPREF running in user mode\n" if($nrconf{verbosity} > 1); } else { print STDERR "$LOGPREF running in root mode\n" if($nrconf{verbosity} > 1); } # get current runlevel, fallback to '2' my $runlevel = `who -r` || ''; chomp($runlevel); $runlevel = 2 unless($runlevel =~ s/^.+run-level (\S)\s.+$/$1/); # get UI if(defined($opt_u)) { if ($opt_u eq '?') { print STDERR join("\n\t", __(q(Available UI packages:)), needrestart_ui_list($nrconf{verbosity}, ($is_tty ? $nrconf{ui} : 'NeedRestart::UI::stdio')))."\n"; exit 0; } else { $nrconf{ui} = $opt_u; } } my $ui = ($opt_b ? NeedRestart::UI->new(0) : needrestart_ui($nrconf{verbosity}, ($is_tty ? $nrconf{ui} : 'NeedRestart::UI::stdio'))); die "Error: no UI class available!\n" unless(defined($ui)); # enable/disable checks unless(defined($opt_k) || defined($opt_l) || defined($opt_w)) { $opt_k = ($uid ? undef : 1); $opt_l = 1; $opt_w = ($uid ? undef : 1); } sub parse_lsbinit($) { my $rc = '/etc/init.d/'.shift; # ignore upstart-job magic if(-l $rc && readlink($rc) eq '/lib/init/upstart-job') { print STDERR "$LOGPREF ignoring $rc since it is a converted upstart job\n" if($nrconf{verbosity} > 1); return (); } open(HLSB, '<', $rc) || die "Can't open $rc: $!\n"; my %lsb; my $found_lsb; my %chkconfig; my $found_chkconfig; while(my $line = ) { chomp($line); unless($found_chkconfig) { if($line =~ /^# chkconfig: (\d+) /) { $chkconfig{runlevels} = $1; $found_chkconfig++ } } elsif($line =~ /^# (\S+): (.+)$/) { $chkconfig{lc($1)} = $2; } unless($found_lsb) { $found_lsb++ if($line =~ /^### BEGIN INIT INFO/); next; } elsif($line =~ /^### END INIT INFO/) { last; } $lsb{lc($1)} = $2 if($line =~ /^# ([^:]+):\s+(.+)$/); } # convert chkconfig tags to LSB tags if($found_chkconfig && !$found_lsb) { print STDERR "$LOGPREF $rc is missing LSB tags, found chkconfig tags instead\n" if($nrconf{verbosity} > 1); $found_lsb++; $lsb{pidfiles} = [$chkconfig{pidfile}]; $lsb{q(default-start)} = $chkconfig{runlevels}; } unless($found_lsb) { print STDERR "WARNING: $rc has no LSB tags!\n" unless(%lsb); return (); } # pid file heuristic unless(exists($lsb{pidfiles})) { my $found = 0; my %pidfiles; while(my $line = ) { if($line =~ m@(\S*/run/[^/]+.pid)@ && -r $1) { $pidfiles{$1}++; $found++; } } $lsb{pidfiles} = [keys %pidfiles] if($found); } close(HLSB); return %lsb; } print STDERR "$LOGPREF systemd detected\n" if($nrconf{verbosity} > 1 && $is_systemd); print STDERR "$LOGPREF container detected\n" if($nrconf{verbosity} > 1 && $is_container); sub systemd_refuse_restart { my $svc = shift; my $systemctl = nr_fork_pipe($nrconf{verbosity} > 1, qq(systemctl), qq(show), qq(--property=RefuseManualStop), $svc); my $ret = <$systemctl>; close($systemctl); if($ret && $ret =~ /^RefuseManualStop=yes/) { print STDERR "$LOGPREF systemd refuses restarts of $svc\n" if($nrconf{verbosity} > 1); return 1; } return 0; } my @systemd_restart; sub restart_cmd($) { my $rc = shift; my $restcmd = "$nrconf{restart_d}/$rc"; if(-x $restcmd) { print STDERR "$LOGPREF using restart.d file $rc\n" if($nrconf{verbosity} > 1); ($restcmd); } elsif($rc =~ /.+\.service$/) { if($nrconf{systemctl_combine}) { push(@systemd_restart, $rc); (); } else { (qw(systemctl restart), $rc); } } else { if($is_systemd) { if($nrconf{systemctl_combine}) { push(@systemd_restart, qq($rc.service)); (); } else { (qw(systemctl restart), qq($rc.service)); } } else { (q(service), $rc, q(restart)); } } } # map UID to username (cached) my %uidcache; sub uid2name($) { my $uid = shift; return $uidcache{$uid} if(exists($uidcache{$uid})); return $uidcache{$uid} = getpwuid($uid) || $uid; } my %nagios = ( # kernel kstr => q(unknown), kret => 3, kperf => q(U), # uCode mstr => q(unknown), mret => 3, mperf => q(U), # services sstr => q(unknown), sret => 3, sperf => q(U), # sessions ustr => q(unknown), uret => 3, uperf => q(U), ); print "NEEDRESTART-VER: $NeedRestart::VERSION\n" if($opt_b && !$opt_p); my %restart; my %sessions; my @easy_hints; if(defined($opt_l)) { my @ign_pids=($$, getppid()); # inspect only pids my $ptable = nr_ptable(); # find session parent sub findppid($@) { my $uid = shift; my ($pid, @pids) = @_; if($ptable->{$pid}->{ppid} == 1) { return $pid if($ptable->{$pid}->{uid} == $uid); return undef; } foreach my $pid (@pids) { my $ppid = &findppid($uid, $pid); return $ppid if($ppid); } return $pid; } $ui->progress_prep(scalar keys %$ptable, __ 'Scanning processes...'); my %stage2; for my $pid (sort {$a <=> $b} keys %$ptable) { $ui->progress_step; # user-mode: skip foreign processes next if($uid && $ptable->{$pid}->{uid} != $uid); # skip myself next if(grep {$pid == $_} @ign_pids); my $restart = 0; my $exe = nr_readlink($pid); # ignore kernel threads next unless(defined($exe)); # orphaned binary $restart++ if (defined($exe) && $exe =~ s/ \(deleted\)$//); # Linux $restart++ if (defined($exe) && $exe =~ s/^\(deleted\)//); # Linux VServer print STDERR "$LOGPREF #$pid uses obsolete binary $exe\n" if($restart && $nrconf{verbosity} > 1); # ignore blacklisted binaries next if(grep { $exe =~ /$_/; } @{$nrconf{blacklist}}); # read file mappings (Linux 2.0+) unless($restart) { if(open(HMAP, '<', "/proc/$pid/maps")) { while() { chomp; my ($maddr, $mperm, $moffset, $mdev, $minode, $path) = split(/\s+/, $_, 6); # skip special handles and non-executable mappings next unless(defined($path) && $minode != 0 && $path ne '' && $mperm =~ /x/); # skip special device paths next if(scalar grep { $path =~ /$_/; } @{$nrconf{blacklist_mappings}}); # removed executable mapped files if($path =~ s/ \(deleted\)$// || # Linux $path =~ s/^\(deleted\)//) { # Linux VServer print STDERR "$LOGPREF #$pid uses deleted $path\n" if($nrconf{verbosity} > 1); $restart++; last; } # check for outdated lib mappings unless($nrconf{skip_mapfiles} == 1) { my @paths = ("/proc/$pid/map_files/$maddr", "/proc/$pid/root/$path"); my ($testp) = grep { -e $_; } @paths; unless($testp) { unless($path =~ m@^(/var)?/tmp/@ || $path =~ m@^(/var)?/run/@ || $nrconf{skip_mapfiles} == -1) { print STDERR "$LOGPREF #$pid uses non-existing $path\n" if($nrconf{verbosity} > 1); $restart++; last; } next; } # get on-disk info my ($sdev, $sinode) = stat($testp); my @sdevs = ( # glibc gnu_dev_* definition from sysmacros.h sprintf("%02x:%02x", (($sdev >> 8) & 0xfff) | (($sdev >> 32) & ~0xfff), (($sdev & 0xff) | (($sdev >> 12) & ~0xff))), # Traditional definition of major(3) and minor(3) sprintf("%02x:%02x", $sdev >> 8, $sdev & 0xff), # kFreeBSD: /proc//maps does not contain device IDs qq(00:00) ); # Don't compare device numbers on anon filesystems # w/o a backing device (like OpenVZ's simfs). my $major = (($sdev >> 8) & 0xfff) | (($sdev >> 32) & ~0xfff); $mdev = "00:00" if ($major == 0 || $major == 144 || $major == 145 || $major == 146); # compare maps content vs. on-disk unless($minode eq $sinode && ((grep {$mdev eq $_} @sdevs) || # BTRFS breaks device ID mapping completely... # ignoring unnamed device IDs for now $mdev =~ /^00:/)) { print STDERR "$LOGPREF #$pid uses obsolete $path\n" if($nrconf{verbosity} > 1); $restart++; last; } } } close(HMAP); } else { print STDERR "$LOGPREF #$pid could not open maps: $!\n" if($nrconf{verbosity} > 1); } } unless($restart || !$nrconf{interpscan}) { $restart++ if(needrestart_interp_check($nrconf{verbosity} > 1, $pid, $exe, $nrconf{blacklist_interp})); } # handle containers (LXC, docker, etc.) next if($restart && needrestart_cont_check($nrconf{verbosity} > 1, $pid, $exe)); # restart needed? next unless($restart); # handle user sessions if($ptable->{$pid}->{ttydev} ne '' && (!$is_systemd || !$nrconf{has_pam_systemd})) { my $ttydev = realpath( $ptable->{$pid}->{ttydev} ); print STDERR "$LOGPREF #$pid part of user session: uid=$ptable->{$pid}->{uid} sess=$ttydev\n" if($nrconf{verbosity} > 1); push(@{ $sessions{ $ptable->{$pid}->{uid} }->{ $ttydev }->{ $ptable->{$pid}->{fname} } }, $pid); # add session processes to stage2 only in user mode $stage2{$pid} = $exe if($uid); next; } # find parent process my $ppid = $ptable->{$pid}->{ppid}; if($ppid != $pid && $ppid > 1 && !$uid) { print STDERR "$LOGPREF #$pid is a child of #$ppid\n" if($nrconf{verbosity} > 1); if($uid && $ptable->{$ppid}->{uid} != $uid) { print STDERR "$LOGPREF #$ppid is a foreign process\n" if($nrconf{verbosity} > 1); $stage2{$pid} = $exe; } else { unless(exists($stage2{$ppid})) { my $pexe = nr_readlink($ppid); # ignore kernel threads next unless(defined($pexe)); $stage2{$ppid} = $pexe; } } } else { print STDERR "$LOGPREF #$pid is not a child\n" if($nrconf{verbosity} > 1 && !$uid); $stage2{$pid} = $exe; } } $ui->progress_fin; if(scalar keys %stage2 && !$uid) { $ui->progress_prep(scalar keys %stage2, __ 'Scanning candidates...'); foreach my $pid (sort {$a <=> $b} keys %stage2) { $ui->progress_step; # skip myself next if(grep {$pid == $_} @ign_pids); my $exe = nr_readlink($pid); $exe =~ s/ \(deleted\)$//; # Linux $exe =~ s/^\(deleted\)//; # Linux VServer print STDERR "$LOGPREF #$pid exe => $exe\n" if($nrconf{verbosity} > 1); # try to find interpreter source file ($exe) = (needrestart_interp_source($nrconf{verbosity} > 1, $pid, $exe), $exe); # ignore blacklisted binaries next if(grep { $exe =~ /$_/; } @{$nrconf{blacklist}}); if($is_systemd) { # systemd manager if($pid == 1 && $exe =~ m@^/lib/systemd/systemd@) { print STDERR "$LOGPREF #$pid is systemd manager\n" if($nrconf{verbosity} > 1); $restart{q(systemd-manager)}++; next; } # get unit name from /proc//cgroup if(open(HCGROUP, qq(/proc/$pid/cgroup))) { my ($rc) = map { chomp; my ($id, $type, $value) = split(/:/); if($type ne q(name=systemd)) { (); } else { if($value =~ m@/user-(\d+)\.slice/session-(\d+)\.scope@) { print STDERR "$LOGPREF #$pid part of user session: uid=$1 sess=$2\n" if($nrconf{verbosity} > 1); push(@{ $sessions{$1}->{"session #$2"}->{ $ptable->{$pid}->{fname} } }, $pid); next; } if($value =~ m@/user\@(\d+)\.service@) { print STDERR "$LOGPREF #$pid part of user manager service: uid=$1\n" if($nrconf{verbosity} > 1); push(@{ $sessions{$1}->{'user manager service'}->{ $ptable->{$pid}->{fname} } }, $pid); next; } elsif($value =~ m@/([^/]+\.service)$@) { ($1); } else { print STDERR "$LOGPREF #$pid unexpected cgroup '$value'\n" if($nrconf{verbosity} > 1); (); } } } ; close(HCGROUP); if($rc) { print STDERR "$LOGPREF #$pid is $rc\n" if($nrconf{verbosity} > 1); $restart{$rc}++; next; } } # did not get the unit name, yet - try systemctl status print STDERR "$LOGPREF /proc/$pid/cgroup: $!\n" if($nrconf{verbosity} > 1 && $!); print STDERR "$LOGPREF trying systemctl status\n" if($nrconf{verbosity} > 1); my $systemctl = nr_fork_pipe($nrconf{verbosity} > 1, qq(systemctl), qq(-n), qq(0), qq(--full), qq(status), $pid); my $ret = <$systemctl>; close($systemctl); if(defined($ret) && $ret =~ /([^\s]+\.service)( |$)/) { my $s = $1; print STDERR "$LOGPREF #$pid is $s\n" if($nrconf{verbosity} > 1); $restart{$s}++; $s =~ s/\.service$//; delete($restart{$s}); next; } } else { # sysv init if($pid == 1 && $exe =~ m@^/sbin/init@) { print STDERR "$LOGPREF #$pid is sysv init\n" if($nrconf{verbosity} > 1); $restart{q(sysv-init)}++; next; } } my $pkg; foreach my $hook (nsort <$nrconf{hook_d}/*>) { print STDERR "$LOGPREF #$pid running $hook\n" if($nrconf{verbosity} > 1); my $found = 0; my $prun = nr_fork_pipe($nrconf{verbosity} > 1, $hook, ($nrconf{verbosity} > 1 ? qw(-v) : ()), $exe); my @nopids; while(<$prun>) { chomp; my @v = split(/\|/); if($v[0] eq 'PACKAGE' && $v[1]) { $pkg = $v[1]; print STDERR "$LOGPREF #$pid package: $v[1]\n" if($nrconf{verbosity} > 1); next; } if($v[0] eq 'RC') { my %lsb = parse_lsbinit($v[1]); unless(%lsb && exists($lsb{'default-start'})) { # If the script has no LSB tags we consider to call it later - they # are broken anyway. print STDERR "$LOGPREF no LSB headers found at $v[1]\n" if($nrconf{verbosity} > 1); push(@nopids, $v[1]); } # In the run-levels S and 1 no daemons are being started (normaly). # We don't call any rc.d script not started in the current run-level. elsif($lsb{'default-start'} =~ /$runlevel/) { # If a pidfile has been found, try to look for the daemon and ignore # any forked/detached childs (just a heuristic due Debian Bug#721810). if(exists($lsb{pidfiles})) { foreach my $pidfile (@{ $lsb{pidfiles} }) { open(HPID, '<', "$pidfile") || next; my $p = ; close(HPID); if(int($p) == $pid) { print STDERR "$LOGPREF #$pid has been started by $v[1] - triggering\n" if($nrconf{verbosity} > 1); $restart{$v[1]}++; $found++; last; } } } else { print STDERR "$LOGPREF no pidfile reference found at $v[1]\n" if($nrconf{verbosity} > 1); push(@nopids, $v[1]); } } else { print STDERR "$LOGPREF #$pid rc.d script $v[1] should not start in the current run-level($runlevel)\n" if($nrconf{verbosity} > 1); } } } # No perfect hit - call any rc scripts instead. if(!$found && $#nopids > -1) { foreach my $rc (@nopids) { if($is_systemd && exists($restart{"$rc.service"})) { print STDERR "$LOGPREF #$pid rc.d script $rc seems to be superseeded by $rc.service\n" if($nrconf{verbosity} > 1); } else { $restart{$rc}++; } } $found++; } last if($found); } } $ui->progress_fin; } # List user's processes in user-mode if($uid && scalar %stage2) { my %fnames; foreach my $pid (keys %stage2) { push(@{$fnames{ $ptable->{$pid}->{fname} }}, $pid); } if($opt_b) { print map { "NEEDRESTART-PID: $_=".join(',', @{ $fnames{$_} })."\n"; } nsort keys %fnames; } else { $ui->notice(__ 'Your outdated processes:'); $ui->notice(join(', ',map { $_.'['.join(', ', @{ $fnames{$_} }).']'; } nsort keys %fnames)); } } } # Apply rc/service blacklist foreach my $rc (keys %restart) { next unless(scalar grep { $rc =~ /$_/; } @{$nrconf{blacklist_rc}}); print STDERR "$LOGPREF $rc is blacklisted -> ignored\n" if($nrconf{verbosity} > 1); delete($restart{$rc}); } # Skip kernel and uCode stuff within containers if($is_container || needrestart_cont_check($nrconf{verbosity} > 1, 1, nr_readlink(1), 1)) { print STDERR "$LOGPREF inside container, skipping kernel and microcode checks\n" if($nrconf{verbosity} > 1); $opt_k = undef; $opt_w = undef; } my ($ucode_result, %ucode_vars) = (NRM_UNKNOWN); if(defined($opt_w)) { ($ucode_result, %ucode_vars) = ($nrconf{ucodehints} || $opt_w ? nr_ucode_check($nrconf{verbosity} > 1, $ui) : ()); } if(defined($opt_k)) { my ($kresult, %kvars) = ($nrconf{kernelhints} || $opt_b ? nr_kernel_check($nrconf{verbosity} > 1, $ui) : ()); if(defined($kresult)) { if($opt_b) { unless($opt_p) { print "NEEDRESTART-KCUR: $kvars{KVERSION}\n"; print "NEEDRESTART-KEXP: $kvars{EVERSION}\n" if(defined($kvars{EVERSION})); print "NEEDRESTART-KSTA: $kresult\n"; } else { $nagios{kstr} = $kvars{KVERSION}; if($kresult == NRK_VERUPGRADE) { $nagios{kstr} .= "!=$kvars{EVERSION}"; $nagios{kret} = $nrconf{q(nagios-status)}->{kernel}; $nagios{kperf} = 2; } elsif($kresult == NRK_ABIUPGRADE) { $nagios{kret} = $nrconf{q(nagios-status)}->{kernel}; $nagios{kperf} = 1; } elsif($kresult == NRK_NOUPGRADE) { $nagios{kret} = 0; $nagios{kperf} = 0; } if($nagios{kret} == 1) { $nagios{kstr} .= " (!)"; } elsif($nagios{kret} == 2) { $nagios{kstr} .= " (!!)"; } } } else { if($kresult == NRK_NOUPGRADE) { unless($opt_m eq 'e') { $ui->vspace(); $ui->notice(($kvars{ABIDETECT} ? __('Running kernel seems to be up-to-date.') : __('Running kernel seems to be up-to-date (ABI upgrades are not detected).'))) } } elsif($kresult == NRK_ABIUPGRADE) { push(@easy_hints, __ 'an outdated kernel image') if($opt_m eq 'e'); if($nrconf{kernelhints} < 0) { $ui->vspace(); $ui->notice(__x( 'The currently running kernel version is {kversion} and there is an ABI compatible upgrade pending.', kversion => $kvars{KVERSION}, )); } else { $ui->announce_abi(%kvars); } } elsif($kresult == NRK_VERUPGRADE) { push(@easy_hints, __ 'an outdated kernel image') if($opt_m eq 'e'); if($nrconf{kernelhints} < 0) { $ui->vspace(); $ui->notice(__x( 'The currently running kernel version is {kversion} which is not the expected kernel version {eversion}.', kversion => $kvars{KVERSION}, eversion => $kvars{EVERSION}, )); } else { $ui->announce_ver(%kvars); } } else { $ui->vspace(); $ui->notice(__ 'Failed to retrieve available kernel versions.'); } } } } if(defined($opt_w)) { if($opt_b) { unless($opt_p) { print "NEEDRESTART-UCSTA: $ucode_result\n"; if($ucode_result != NRM_UNKNOWN) { print "NEEDRESTART-UCCUR: $ucode_vars{CURRENT}\n"; print "NEEDRESTART-UCEXP: $ucode_vars{AVAIL}\n"; } } else { if($ucode_result == NRM_OBSOLETE) { $nagios{mstr} = "OBSOLETE"; $nagios{mret} = $nrconf{q(nagios-status)}->{ucode}; $nagios{mperf} = 1; } elsif($ucode_result == NRM_CURRENT) { $nagios{mstr} = "CURRENT"; $nagios{mret} = 0; $nagios{mperf} = 0; } if($nagios{mret} == 1) { $nagios{mstr} .= " (!)"; } elsif($nagios{mret} == 2) { $nagios{mstr} .= " (!!)"; } } } else { if($ucode_result == NRM_CURRENT) { unless($opt_m eq 'e') { $ui->vspace(); $ui->notice(__('The processor microcode seems to be up-to-date.')); } } elsif($ucode_result == NRM_OBSOLETE) { push(@easy_hints, __ 'outdated processor microcode') if($opt_m eq 'e'); if($nrconf{ucodehints}) { $ui->announce_ucode(%ucode_vars); } } else { $ui->vspace(); $ui->notice(__ 'Failed to check for processor microcode upgrades.'); } } } if(defined($opt_l) && !$uid) { ## SERVICES $ui->vspace(); unless(scalar %restart) { $ui->notice(__ 'No services need to be restarted.') unless($opt_b || $opt_m eq 'e'); if($opt_p) { $nagios{sstr} = q(none); $nagios{sret} = 0; $nagios{sperf} = 0; } } else { if($opt_m eq 'e' && $opt_r ne 'i') { push(@easy_hints, __ 'outdated binaries'); } elsif($opt_b || $opt_r ne 'i') { my @skipped_services; my @refused_services; $ui->notice(__ 'Services to be restarted:') if($opt_r eq 'l'); $ui->notice(__ 'Restarting services...') if($opt_r eq 'a'); if($opt_p) { $nagios{sstr} = (scalar keys %restart); $nagios{sret} = $nrconf{q(nagios-status)}->{services}; $nagios{sperf} = (scalar keys %restart); if($nagios{sret} == 1) { $nagios{sstr} .= " (!)"; } elsif($nagios{sret} == 2) { $nagios{sstr} .= " (!!)"; } } foreach my $rc (sort { lc($a) cmp lc($b) } keys %restart) { # always combine restarts in one systemctl command local $nrconf{systemctl_combine} = 1 unless($opt_r eq 'l'); if($opt_b) { print "NEEDRESTART-SVC: $rc\n" unless($opt_p); next; } # record service which can not be restarted if($is_systemd && systemd_refuse_restart($rc)) { push(@refused_services, $rc); next; } # don't restart greylisted services... my $restart = !$nrconf{defno}; foreach my $re (keys %{$nrconf{override_rc}}) { next unless($rc =~ /$re/); $restart = $nrconf{override_rc}->{$re}; last; } # ...but complain about them unless($restart) { push(@skipped_services, $rc); next; } my @cmd = restart_cmd($rc); next unless($#cmd > -1); $ui->command(join(' ', '', @cmd)); $ui->runcmd(sub { system(@cmd) if($opt_r eq 'a'); }); } unless($#systemd_restart == -1) { my @cmd = (qq(systemctl), qq(restart), @systemd_restart); $ui->command(join(' ', '', @cmd)); $ui->runcmd(sub { system(@cmd) if($opt_r eq 'a'); }); } @systemd_restart = (); if($#skipped_services > -1) { $ui->vspace(); $ui->notice(__ 'Service restarts being deferred:'); foreach my $rc (sort @skipped_services) { my @cmd = restart_cmd($rc); $ui->command(join(' ', '', @cmd)) if($#cmd > -1); } unless($#systemd_restart == -1) { my @cmd = (qq(systemctl), qq(restart), @systemd_restart); $ui->command(join(' ', '', @cmd)); } } # report services restarts refused by systemd if($#refused_services > -1) { $ui->vspace(); $ui->notice(__ 'Service restarts being refused by systemd:'); foreach my $rc (sort @refused_services) { $ui->command(qq( $rc)); } } } else { my $o = 0; my @skipped_services = keys %restart; # filter service units which are refused to be restarted my @refused_services; my %rs = map { my $rc = $_; if($is_systemd) { if(systemd_refuse_restart($rc)) { push(@refused_services, $rc); @skipped_services = grep { $_ ne $rc; } @skipped_services; (); } else { ($rc => 1); } } else { ($rc => 1); } } keys %restart; $ui->notice(__ 'Restarting services...'); $ui->query_pkgs(__('Services to be restarted:'), $nrconf{defno}, \%rs, $nrconf{override_rc}, sub { # always combine restarts in one systemctl command local $nrconf{systemctl_combine} = 1; my $rc = shift; @skipped_services = grep { $_ ne $rc; } @skipped_services; my @cmd = restart_cmd($rc); return unless($#cmd > -1); $ui->command(join(' ', '', @cmd)); system(@cmd); }); if($#systemd_restart > -1) { my @cmd = (qw(systemctl restart), @systemd_restart); $ui->command(join(' ', '', @cmd)); $ui->runcmd(sub { system(@cmd); }); } @systemd_restart = (); if($#skipped_services > -1) { $ui->notice(__ 'Service restarts being deferred:'); foreach my $rc (sort @skipped_services) { my @cmd = restart_cmd($rc); $ui->command(join(' ', '', @cmd)) if($#cmd > -1); } unless($#systemd_restart == -1) { my @cmd = (qq(systemctl), qq(restart), @systemd_restart); $ui->command(join(' ', '', @cmd)); } } # report services restarts refused by systemd if($#refused_services > -1) { $ui->notice(__ 'Service restarts being refused by systemd:'); foreach my $rc (sort @refused_services) { $ui->command(qq( $rc)); } } } } ## CONTAINERS $ui->vspace(); @systemd_restart = (); my %conts = needrestart_cont_get($nrconf{verbosity} > 1); unless(scalar %conts) { $ui->notice(__ 'No containers need to be restarted.') unless($opt_b || $opt_m eq 'e'); if($opt_p) { $nagios{cstr} = q(none); $nagios{cret} = 0; $nagios{cperf} = 0; } } else { if($opt_m eq 'e' && $opt_r ne 'i') { push(@easy_hints, __ 'outdated containers'); } elsif($opt_b || $opt_r ne 'i') { my @skipped_containers; $ui->notice(__ 'Containers to be restarted:') if($opt_r eq 'l'); $ui->notice(__ 'Restarting containers...') if($opt_r eq 'a'); if($opt_p) { $nagios{cstr} = (scalar keys %conts); $nagios{cret} = $nrconf{q(nagios-status)}->{containers}; $nagios{cperf} = (scalar keys %conts); if($nagios{cret} == 1) { $nagios{cstr} .= " (!)"; } elsif($nagios{cret} == 2) { $nagios{cstr} .= " (!!)"; } } foreach my $cont (sort { lc($a) cmp lc($b) } keys %conts) { if($opt_b) { print "NEEDRESTART-CONT: $cont\n" unless($opt_p); next; } # don't restart greylisted containers... my $restart = !$nrconf{defno}; foreach my $re (keys %{$nrconf{override_cont}}) { next unless($cont =~ /$re/); $restart = $nrconf{override_cont}->{$re}; last; } # ...but complain about them unless($restart) { push(@skipped_containers, $cont); next; } $ui->command(join(' ', '', @{ $conts{$cont} })); $ui->runcmd(sub { system(@{ $conts{$cont} }) if($opt_r eq 'a'); }); } if($#skipped_containers > -1) { $ui->notice(__ 'Container restarts being deferred:'); foreach my $cont (sort @skipped_containers) { $ui->command(join(' ', '', @{ $conts{$cont} })); } } } else { my $o = 0; $ui->notice(__ 'Restarting containers...'); $ui->query_conts(__('Containers to be restarted:'), $nrconf{defno}, \%conts, $nrconf{override_cont}, sub { my $cont = shift; $ui->command(join(' ', '', @{ $conts{$cont} })); system(@{ $conts{$cont} }); }); } } ## SESSIONS $ui->vspace(); # list and notify user sessions unless(scalar keys %sessions) { $ui->notice(__ 'No user sessions are running outdated binaries.') unless($opt_b || $opt_m eq 'e'); if($opt_p) { $nagios{ustr} = 'none'; $nagios{uret} = 0; $nagios{uperf} = 0; } } else { if($opt_m eq 'e') { push(@easy_hints, __ 'outdated sessions'); } else { $ui->notice(__ 'User sessions running outdated binaries:'); } if($opt_p) { my $count = sum map { scalar keys %{ $sessions{$_} } } keys %sessions; $nagios{ustr} = $count; $nagios{uret} = $nrconf{q(nagios-status)}->{sessions}; $nagios{uperf} = $count; if($nagios{uret} == 1) { $nagios{ustr} .= " (!)"; } elsif($nagios{uret} == 2) { $nagios{ustr} .= " (!!)"; } } unless($opt_p || $opt_b) { foreach my $uid (sort { ncmp(uid2name($a), uid2name($b)); } keys %sessions) { foreach my $sess (sort keys %{ $sessions{$uid} }) { my $fnames = join(', ',map { $_.'['.join(',', @{ $sessions{$uid}->{$sess}->{$_} }).']'; } nsort keys %{ $sessions{$uid}->{$sess} }); $ui->notice(' '.uid2name($uid)." @ $sess: $fnames") unless($opt_m eq 'e'); if($nrconf{sendnotify}) { local %ENV; $ENV{NR_UID} = $uid; $ENV{NR_USERNAME} = uid2name($uid); $ENV{NR_SESSION} = $sess; $ENV{NR_SESSPPID} = findppid($uid, sort map { @$_; } values %{ $sessions{$uid}->{$sess} }); foreach my $bin (nsort <$nrconf{notify_d}/*>) { next unless(-x $bin); next if($bin =~ /(~|\.dpkg-[^.]+)$/); print STDERR "$LOGPREF run $bin\n" if($nrconf{verbosity} > 1); my $pipe = nr_fork_pipew($nrconf{verbosity} > 1, $bin); print $pipe "$fnames\n"; last if(close($pipe)); } } } } } } } # easy mode: print hint on outdated stuff if(scalar @easy_hints) { my $t = pop(@easy_hints); my $h = join(', ', @easy_hints); $ui->announce_ehint(EHINT => ($h ? join(' ', $h, __ 'and', '') : '') . $t); } # nagios plugin output if($opt_p) { my %states = ( 0 => q(OK), 1 => q(WARN), 2 => q(CRIT), 3 => q(UNKN), ); my ($ret) = reverse sort (($opt_k ? $nagios{kret} : ()), ($opt_w ? $nagios{mret} : ()), ($opt_l ? ($nagios{sret}, $nagios{cret}, $nagios{uret}) : ())); print "$states{$ret} - ", join(', ', ($opt_k ? "Kernel: $nagios{kstr}" : ()), ($opt_w ? "Microcode: $nagios{mstr}" : ()), ($opt_l ? "Services: $nagios{sstr}" : ()), ($opt_l ? "Containers: $nagios{cstr}" : ()), ($opt_l ? "Sessions: $nagios{ustr}" : ()), ), '|', join(' ', ($opt_k ? "Kernel=$nagios{kperf};0;;0;2" : ()), ($opt_w ? "Microcode=$nagios{mperf};0;;0;1" : ()), ($opt_l ? "Services=$nagios{sperf};;0;0" : ()), ($opt_l ? "Containers=$nagios{cperf};;0;0" : ()), ($opt_l ? "Sessions=$nagios{uperf};0;;0" : ()), ), "\n"; if(scalar %restart) { print "Services:", join("\n- ", '', sort keys %restart), "\n"; } my %conts = needrestart_cont_get($nrconf{verbosity} > 1); if(scalar %conts) { print "Containers:", join("\n- ", '', sort keys %conts), "\n"; } if(scalar %sessions) { print "Sessions:", join("\n- ", '', map { my $uid = $_; my $user = uid2name($uid); my @ret; foreach my $sess (sort keys %{ $sessions{$uid} }) { push(@ret, "$user \@ $sess"); } @ret; } sort { ncmp(uid2name($a), uid2name($b)); } keys %sessions), "\n"; } exit $ret; } needrestart-3.1/perl/000077500000000000000000000000001325725522600146505ustar00rootroot00000000000000needrestart-3.1/perl/Makefile.PL000066400000000000000000000004521325725522600166230ustar00rootroot00000000000000use ExtUtils::MakeMaker; WriteMakefile( 'AUTHOR' => 'Thomas Liske ', 'LICENSE' => 'gpl', 'NAME' => 'NeedRestart', 'PREREQ_PM' => { Module::Find => 0, Module::ScanDeps => 0, Proc::ProcessTable => 0, Sort::Naturally => 0, Term::ReadKey => 0. }, ); needrestart-3.1/perl/lib/000077500000000000000000000000001325725522600154165ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart.pm000066400000000000000000000135331325725522600202010ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart; use strict; use warnings; use Module::Find; use NeedRestart::Utils; use NeedRestart::CONT; use Sort::Naturally; use constant { NEEDRESTART_PRIO_NOAUTO => 0, NEEDRESTART_PRIO_LOW => 1, NEEDRESTART_PRIO_MEDIUM => 10, NEEDRESTART_PRIO_HIGH => 100, }; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( NEEDRESTART_PRIO_NOAUTO NEEDRESTART_PRIO_LOW NEEDRESTART_PRIO_MEDIUM NEEDRESTART_PRIO_HIGH needrestart_ui needrestart_ui_list needrestart_interp_check needrestart_interp_source needrestart_cont_check needrestart_cont_get needrestart_cont_cmd ); our @EXPORT_OK = qw( needrestart_ui_register needrestart_ui_init needrestart_interp_register needrestart_cont_register ); our %EXPORT_TAGS = ( ui => [qw( NEEDRESTART_PRIO_LOW NEEDRESTART_PRIO_MEDIUM NEEDRESTART_PRIO_HIGH needrestart_ui_register needrestart_ui_init )], interp => [qw( needrestart_interp_register )], cont => [qw( needrestart_cont_register )], ); our $VERSION = '3.1'; my $LOGPREF = '[Core]'; my %UIs; sub needrestart_ui_register($$) { my $pkg = shift; my $prio = shift; $UIs{$pkg} = $prio; } sub needrestart_ui_init($$) { my $verbosity = shift; my $prefui = shift; # load preferred UI module if(defined($prefui)) { return if(eval "use $prefui; 1;"); } # autoload UI modules foreach my $module (findsubmod NeedRestart::UI) { unless(eval "use $module; 1;") { warn "Error loading $module: $@\n" if($@ && ($verbosity > 1)); } } } sub needrestart_ui { my $verbosity = shift; my $prefui = shift; needrestart_ui_init($verbosity, $prefui) unless(%UIs); my ($ui) = sort { ncmp($UIs{$b}, $UIs{$a}) } grep { ($UIs{$_} != NEEDRESTART_PRIO_NOAUTO) || ( defined($prefui) && ($prefui eq $_) ) } keys %UIs; return undef unless($ui); print STDERR "$LOGPREF Using UI '$ui'...\n" if($verbosity > 1); return $ui->new($verbosity); } sub needrestart_ui_list { my $verbosity = shift; my $prefui = shift; needrestart_ui_init($verbosity, $prefui) unless(%UIs); return (sort { ncmp($UIs{$b}, $UIs{$a}) } keys %UIs); } my %Interps; my %InterpCache; my $idebug; sub needrestart_interp_register($) { my $pkg = shift; $Interps{$pkg} = new $pkg($idebug); } sub needrestart_interp_init($) { $idebug = shift; # autoload Interp modules foreach my $module (findsubmod NeedRestart::Interp) { unless(eval "use $module; 1;") { warn "Error loading $module: $@\n" if($@ && $idebug); } } } sub needrestart_interp_check($$$$) { my $debug = shift; my $pid = shift; my $bin = shift; my $blacklist = shift; needrestart_interp_init($debug) unless(%Interps); foreach my $interp (values %Interps) { if($interp->isa($pid, $bin)) { print STDERR "$LOGPREF #$pid is a ".(ref $interp)."\n" if($debug); my $ps = nr_ptable_pid($pid); my %files = $interp->files($pid, \%InterpCache); foreach my $path (keys %files) { next unless(scalar grep { $path =~ /$_/; } @{$blacklist}); print STDERR "$LOGPREF blacklisted: $path\n" if($debug); delete($files{$path}); } if(grep {!defined($_) || $_ > $ps->start} values %files) { if($debug) { print STDERR "$LOGPREF #$pid uses obsolete script file(s):"; print STDERR join("\n$LOGPREF #$pid ", '', map {(!defined($files{$_}) || $files{$_} > $ps->start ? $_ : ())} keys %files); print STDERR "\n"; } return 1; } } } return 0; } sub needrestart_interp_source($$$) { my $debug = shift; my $pid = shift; my $bin = shift; needrestart_interp_init($debug) unless(%Interps); foreach my $interp (values %Interps) { if($interp->isa($pid, $bin)) { print STDERR "$LOGPREF #$pid is a ".(ref $interp)."\n" if($debug); my $src = $interp->source($pid); print STDERR "$LOGPREF #$pid source is ".(defined($src) ? $src : 'UNKNOWN')."\n" if($debug); return ($src) if(defined($src));; return (); } } return (); } my %CONT; my $ndebug; sub needrestart_cont_register($) { my $pkg = shift; $CONT{$pkg} = new $pkg($ndebug); } sub needrestart_cont_init($) { $ndebug = shift; # autoload CONT modules foreach my $module (findsubmod NeedRestart::CONT) { unless(eval "use $module; 1;") { warn "Error loading $module: $@\n" if($@ && $ndebug); } } } sub needrestart_cont_check($$$;$) { my $debug = shift; my $pid = shift; my $bin = shift; my $norestart = shift || 0; needrestart_cont_init($debug) unless(scalar keys %CONT); foreach my $cont (values %CONT) { return 1 if($cont->check($pid, $bin, $norestart)); } return 0; } sub needrestart_cont_get($) { my $debug = shift; return map { my $cont = $_; my $n = ref $cont; $n =~ s/^NeedRestart::CONT:://; my %c = $cont->get; map { ("$n $_" => $c{$_}); } sort keys %c; } sort { (ref $a) cmp (ref $b); } values %CONT; } 1; needrestart-3.1/perl/lib/NeedRestart/000077500000000000000000000000001325725522600176365ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart/CONT.pm000066400000000000000000000034011325725522600207350ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::CONT; use strict; use warnings; use NeedRestart::Utils; my $LOGPREF = '[CONT]'; my $nspid = get_nspid(undef, 1); my $ptable = nr_ptable(); sub new { my $class = shift; my $debug = shift; return bless { debug => $debug, nspid => $nspid, }, $class; } sub check { my $self = shift; return 0; } sub get { my $self = shift; return (); } sub get_nspid { my $self = shift; my $pid = shift; my $stat = nr_stat(qq(/proc/$pid/ns/pid)); return $stat->{ino} if($stat); return undef; } sub find_nsparent { my $self = shift; my $pid = shift; return undef unless(exists($ptable->{$pid})); my $ns = $self->get_nspid($ptable->{$pid}->{ppid}); return $ptable->{$pid}->{ppid} if($ns && $ns == $nspid); return $self->find_nsparent($ptable->{$pid}->{ppid}); } 1; needrestart-3.1/perl/lib/NeedRestart/CONT/000077500000000000000000000000001325725522600204015ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart/CONT/LXC.pm000066400000000000000000000050351325725522600213700ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::CONT::LXC; use strict; use warnings; use parent qw(NeedRestart::CONT); use NeedRestart qw(:cont); use NeedRestart::Utils; my $LOGPREF = '[LXC]'; needrestart_cont_register(__PACKAGE__) unless($<); sub new { my $class = shift; my $self = $class->SUPER::new(@_); die "Could not get NS PID of #1!\n" unless(defined($self->{nspid})); $self->{lxc} = {}; $self->{lxd} = {}; $self->{has_lxd} = -x q(/usr/bin/lxc); return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; my $ns = $self->get_nspid($pid); # stop here if no dedicated PID namespace is used return 0 if(!$ns || $ns == $self->{nspid}); unless(open(FCG, qq(/proc/$pid/cgroup))) { print STDERR "$LOGPREF #$pid: unable to open cgroup ($!)\n" if($self->{debug}); return 0; } my $cg; { local $/; $cg = ; close(FCG); } # look for LXC cgroups return unless($cg =~ /^\d+:[^:]+:\/lxc\/([^\/\n]+)($|\/)/m); my $name = $1; my $type = ($self->{has_lxd} && -d qq(/var/lib/lxd/containers/$name) ? 'LXD' : 'LXC'); unless($norestart) { print STDERR "$LOGPREF #$pid is part of $type container '$name' and should be restarted\n" if($self->{debug}); $self->{lc($type)}->{$name}++; } else { print STDERR "$LOGPREF #$pid is part of $type container '$name'\n" if($self->{debug}); } return 1; } sub get { my $self = shift; return (map { ($_ => [qw(lxc-stop --reboot --name), $_]); } keys %{ $self->{lxc} }), (map { ($_ => [qw(lxc restart), $_]); } keys %{ $self->{lxd} }); } 1; needrestart-3.1/perl/lib/NeedRestart/CONT/docker.pm000066400000000000000000000041541325725522600222120ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::CONT::docker; use strict; use warnings; use parent qw(NeedRestart::CONT); use NeedRestart qw(:cont); use NeedRestart::Utils; my $LOGPREF = '[docker]'; needrestart_cont_register(__PACKAGE__) unless($<); sub new { my $class = shift; my $self = $class->SUPER::new(@_); die "Could not get NS PID of #1!\n" unless(defined($self->{nspid})); return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; my $ns = $self->get_nspid($pid); # stop here if no dedicated PID namespace is used return 0 if(!$ns || $ns == $self->{nspid}); unless(open(FCG, qq(/proc/$pid/cgroup))) { print STDERR "$LOGPREF #$pid: unable to open cgroup ($!)\n" if($self->{debug}); return 0; } my $cg; { local $/; $cg = ; close(FCG); } # look for docker cgroups return 0 unless($cg =~ /^\d+:[^:]+:\/system.slice\/docker-(.+)\.scope$/m || $cg =~ /^\d+:[^:]+:\/docker\/([\da-f]+)$/m); print STDERR "$LOGPREF #$pid is part of docker container '$1' and will be ignored\n" if($self->{debug}); return 1; } sub get { my $self = shift; return (); } 1; needrestart-3.1/perl/lib/NeedRestart/CONT/machined.pm000066400000000000000000000045551325725522600225200ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::CONT::machined; use strict; use warnings; use parent qw(NeedRestart::CONT); use NeedRestart qw(:cont); use NeedRestart::Utils; my $LOGPREF = '[machined]'; needrestart_cont_register(__PACKAGE__) unless($<); sub new { my $class = shift; my $self = $class->SUPER::new(@_); die "Could not get NS PID of #1!\n" unless(defined($self->{nspid})); $self->{machined} = {}; return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; my $ns = $self->get_nspid($pid); # stop here if no dedicated PID namespace is used return 0 if(!$ns || $ns == $self->{nspid}); unless(open(FCG, qq(/proc/$pid/cgroup))) { print STDERR "$LOGPREF #$pid: unable to open cgroup ($!)\n" if($self->{debug}); return 0; } my $cg; { local $/; $cg = ; close(FCG); } # look for machined cgroups return 0 unless($cg =~ /^\d+:[^:]+:\/machine.slice\/machine-(.+)\.scope$/m); my $name = $1; unless($norestart) { print STDERR "$LOGPREF #$pid is part of systemd-machined container '$name' and should be restarted\n" if($self->{debug}); $self->{machined}->{$name}++; } else { print STDERR "$LOGPREF #$pid is part of systemd-machined container '$name'\n" if($self->{debug}); } return 1; } sub get { my $self = shift; return map { ($_ => [qw(machinectl reboot), $_]); } keys %{ $self->{machined} }; } 1; needrestart-3.1/perl/lib/NeedRestart/Interp.pm000066400000000000000000000023141325725522600214350ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Interp; use strict; use warnings; sub new { my $class = shift; my $debug = shift; return bless { debug => $debug, }, $class; } sub isa($$) { my $self = shift; return 0; } sub source($$) { return (); } sub files($$) { return (); } 1; needrestart-3.1/perl/lib/NeedRestart/Interp/000077500000000000000000000000001325725522600210775ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart/Interp/Java.pm000066400000000000000000000032121325725522600223140ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Interp::Java; use strict; use warnings; use parent qw(NeedRestart::Interp); use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Java]'; needrestart_interp_register(__PACKAGE__); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@/.+/bin/java@); return 0; } sub source { # n/a (no shebang) return undef; } sub files { my $self = shift; my $pid = shift; my %ret = map { my $stat = nr_stat("/proc/$pid/root/$_"); $_ => ( defined($stat) ? $stat->{ctime} : undef ); } map { my $l = readlink; (defined($l) && $l =~ /\.(class|jar)( \(deleted\))?$/ ? $l : ()); } grep {1;} ; return %ret; } 1; needrestart-3.1/perl/lib/NeedRestart/Interp/Perl.pm000066400000000000000000000120041325725522600223340ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Interp::Perl; use strict; use warnings; use parent qw(NeedRestart::Interp); use Cwd qw(abs_path getcwd); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; use Module::ScanDeps; my $LOGPREF = '[Perl]'; needrestart_interp_register(__PACKAGE__); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@/usr/(local/)?bin/perl@); return 0; } sub source { my $self = shift; my $pid = shift; my $ptable = nr_ptable_pid($pid); unless($ptable->{cwd}) { print STDERR "$LOGPREF #$pid: could not get current working directory, skipping\n" if($self->{debug}); return (); } my $cwd = getcwd(); chdir("/proc/$pid/root/$ptable->{cwd}"); # get original ARGV (my $bin, local @ARGV) = nr_parse_cmd($pid); # eat Perl's command line options my %opts; { local $SIG{__WARN__} = sub { }; getopts('sTtuUWXhvV:cwdt:D:pnaF:l:0:I:m:M:fC:Sx:i:eE:', \%opts); } # skip perl -e '...' calls if(exists($opts{e}) || exists($opts{E})) { chdir($cwd); print STDERR "$LOGPREF #$pid: uses no source file (-e), skipping\n" if($self->{debug}); return undef; } # extract source file unless($#ARGV > -1) { chdir($cwd); print STDERR "$LOGPREF #$pid: could not get a source file, skipping\n" if($self->{debug}); return undef; } my $src = abs_path($ARGV[0]); chdir($cwd); unless(-r $src && -f $src) { print STDERR "$LOGPREF #$pid: source file not found, skipping\n" if($self->{debug}); print STDERR "$LOGPREF #$pid: reduced ARGV: ".join(' ', @ARGV)."\n" if($self->{debug}); return undef; } return $src; } sub files { my $self = shift; my $pid = shift; my $cache = shift; my $ptable = nr_ptable_pid($pid); unless($ptable->{cwd}) { print STDERR "$LOGPREF #$pid: could not get current working directory, skipping\n" if($self->{debug}); return (); } my $cwd = getcwd(); chdir("/proc/$pid/root/$ptable->{cwd}"); # skip the process if the cwd is unreachable (i.e. due to mnt ns) unless(getcwd()) { print STDERR "$LOGPREF #$pid: process cwd is unreachable\n" if($self->{debug}); return (); } # get original ARGV (my $bin, local @ARGV) = nr_parse_cmd($pid); # eat Perl's command line options my %opts; { local $SIG{__WARN__} = sub { }; getopts('sTtuUWXhvV:cwdt:D:pnaF:l:0:I:m:M:fC:Sx:i:eE:', \%opts); } # skip perl -e '...' calls if(exists($opts{e}) || exists($opts{E})) { chdir($cwd); print STDERR "$LOGPREF #$pid: uses no source file (-e), skipping\n" if($self->{debug}); return (); } # extract source file unless($#ARGV > -1) { chdir($cwd); print STDERR "$LOGPREF #$pid: could not get a source file, skipping\n" if($self->{debug}); return (); } my $src = abs_path ($ARGV[0]); unless(-r $src && -f $src) { chdir($cwd); print STDERR "$LOGPREF #$pid: source file not found, skipping\n" if($self->{debug}); print STDERR "$LOGPREF #$pid: reduced ARGV: ".join(' ', @ARGV)."\n" if($self->{debug}); return (); } print STDERR "$LOGPREF #$pid: source=$src\n" if($self->{debug}); # use cached data if avail if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { chdir($cwd); print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; } # prepare include path environment variable my %e = nr_parse_env($pid); local %ENV; if(exists($e{PERL5LIB})) { $ENV{PERL5LIB} = $e{PERL5LIB}; } elsif(exists($ENV{PERL5LIB})) { delete($ENV{PERL5LIB}); } @Module::ScanDeps::IncludeLibs = (exists($opts{I}) ? ($opts{I}) : ()); my $href; { # Silence warnings of Module::ScanDeps for dynamic loaded modules (github issue #41) local $SIG{__WARN__} = sub { }; $href = scan_deps( files => [$src], recurse => 1, ); } my %ret = map { my $stat = nr_stat("/proc/$pid/root/$href->{$_}->{file}"); $href->{$_}->{file} => ( defined($stat) ? $stat->{ctime} : undef ); } keys %$href; chdir($cwd); $cache->{files}->{(__PACKAGE__)}->{$src} = \%ret; return %ret; } 1; needrestart-3.1/perl/lib/NeedRestart/Interp/Python.pm000066400000000000000000000136141325725522600227230ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Interp::Python; use strict; use warnings; use parent qw(NeedRestart::Interp); use Cwd qw(abs_path getcwd); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Python]'; needrestart_interp_register(__PACKAGE__); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@/usr/(local/)?bin/python@); return 0; } sub _scan($$$$$) { my $debug = shift; my $pid = shift; my $src = shift; my $files = shift; my $path = shift; my $fh; open($fh, '<', $src) || return; # find used modules my %modules = map { (/^\s*import\s+(\S+)/ ? ($1 => 1) : (/^\s*from\s+(\S+)\s+import\s+/ ? ($1 => 1) : ())) } <$fh>; close($fh); # track file $files->{$src}++; # scan module files if(scalar keys %modules) { foreach my $module (keys %modules) { $module =~ s@\.@/@g; $module .= '.py'; foreach my $p (@$path) { my $fn = ($p ne '' ? "$p/" : '').$module; &_scan($debug, $pid, $fn, $files, $path) if(!exists($files->{$fn}) && -r $fn && -f $fn); } } } } sub source { my $self = shift; my $pid = shift; my $ptable = nr_ptable_pid($pid); unless($ptable->{cwd}) { print STDERR "$LOGPREF #$pid: could not get current working directory, skipping\n" if($self->{debug}); return (); } my $cwd = getcwd(); chdir("/proc/$pid/root/$ptable->{cwd}"); # get original ARGV (my $bin, local @ARGV) = nr_parse_cmd($pid); # eat Python's command line options my %opts; { local $SIG{__WARN__} = sub { }; getopts('BdEhim:ORQ:sStuvVW:x3?c:', \%opts); } # skip python -c '...' calls if(exists($opts{c})) { chdir($cwd); print STDERR "$LOGPREF #$pid: uses no source file (-c), skipping\n" if($self->{debug}); return undef; } # extract source file unless($#ARGV > -1) { chdir($cwd); print STDERR "$LOGPREF #$pid: could not get a source file, skipping\n" if($self->{debug}); return undef; } my $src = abs_path($ARGV[0]); chdir($cwd); unless(-r $src && -f $src) { print STDERR "$LOGPREF #$pid: source file not found, skipping\n" if($self->{debug}); print STDERR "$LOGPREF #$pid: reduced ARGV: ".join(' ', @ARGV)."\n" if($self->{debug}); return undef; } return $src; } sub files { my $self = shift; my $pid = shift; my $cache = shift; my $ptable = nr_ptable_pid($pid); unless($ptable->{cwd}) { print STDERR "$LOGPREF #$pid: could not get current working directory, skipping\n" if($self->{debug}); return (); } my $cwd = getcwd(); chdir("/proc/$pid/root/$ptable->{cwd}"); # skip the process if the cwd is unreachable (i.e. due to mnt ns) unless(getcwd()) { print STDERR "$LOGPREF #$pid: process cwd is unreachable\n" if($self->{debug}); return (); } # get original ARGV (my $bin, local @ARGV) = nr_parse_cmd($pid); # eat Python's command line options my %opts; { local $SIG{__WARN__} = sub { }; getopts('BdEhim:ORQ:sStuvVW:x3?c:', \%opts); } # skip python -c '...' calls if(exists($opts{c})) { chdir($cwd); print STDERR "$LOGPREF #$pid: uses no source file (-c), skipping\n" if($self->{debug}); return (); } # extract source file unless($#ARGV > -1) { chdir($cwd); print STDERR "$LOGPREF #$pid: could not get a source file, skipping\n" if($self->{debug}); return (); } my $src = abs_path ($ARGV[0]); unless(-r $src && -f $src) { chdir($cwd); print STDERR "$LOGPREF #$pid: source file not found, skipping\n" if($self->{debug}); print STDERR "$LOGPREF #$pid: reduced ARGV: ".join(' ', @ARGV)."\n" if($self->{debug}); return (); } print STDERR "$LOGPREF #$pid: source=$src\n" if($self->{debug}); # use cached data if avail if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; } # prepare include path environment variable my %e = nr_parse_env($pid); local %ENV; if(exists($e{PYTHONPATH})) { $ENV{PYTHONPATH} = $e{PYTHONPATH}; } elsif(exists($ENV{PYTHONPATH})) { delete($ENV{PYTHONPATH}); } # get include path my ($pyread, $pywrite) = nr_fork_pipe2($self->{debug}, $ptable->{exec}, '-'); print $pywrite "import sys\nprint(sys.path)\n"; close($pywrite); my ($path) = <$pyread>; close($pyread); # look for module source files my @path; if(defined($path)) { chomp($path); $path =~ s/^\['//; $path =~ s/'\$//; @path = map { "/proc/$pid/root/$_"; } split("', '", $path); } else { print STDERR "$LOGPREF #$pid: failed to retrieve include path\n" if($self->{debug}); } my %files; _scan($self->{debug}, $pid, $src, \%files, \@path); my %ret = map { my $stat = nr_stat("/proc/$pid/root/$_"); $_ => ( defined($stat) ? $stat->{ctime} : undef ); } keys %files; chdir($cwd); $cache->{files}->{(__PACKAGE__)}->{$src} = \%ret; return %ret; } 1; needrestart-3.1/perl/lib/NeedRestart/Interp/Ruby.pm000066400000000000000000000130411325725522600223550ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Interp::Ruby; use strict; use warnings; use parent qw(NeedRestart::Interp); use Cwd qw(abs_path getcwd); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Ruby]'; needrestart_interp_register(__PACKAGE__); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@/usr/(local/)?bin/ruby@); return 0; } sub _scan($$$$$) { my $debug = shift; my $pid = shift; my $src = shift; my $files = shift; my $path = shift; my $fh; open($fh, '<', $src) || return; # find used modules my %modules = map { (/^\s*load\s+['"]([^'"]+)['"]/ ? ($1 => 1) : (/^\s*require\s+['"]([^'"]+)['"]/ ? ("$1.rb" => 1) : ())) } <$fh>; close($fh); # track file $files->{$src}++; # scan module files if(scalar keys %modules) { foreach my $module (keys %modules) { foreach my $p (@$path) { my $fn = ($p ne '' ? "$p/" : '').$module; &_scan($debug, $pid, $fn, $files, $path) if(!exists($files->{$fn}) && -r $fn && -f $fn); } } } } sub source { my $self = shift; my $pid = shift; my $ptable = nr_ptable_pid($pid); unless($ptable->{cwd}) { print STDERR "$LOGPREF #$pid: could not get current working directory, skipping\n" if($self->{debug}); return (); } my $cwd = getcwd(); chdir("/proc/$pid/root/$ptable->{cwd}"); # get original ARGV (my $bin, local @ARGV) = nr_parse_cmd($pid); # eat Ruby's command line options my %opts; { local $SIG{__WARN__} = sub { }; getopts('SUacdlnpswvy0:C:E:F:I:K:T:W:e:i:r:x:e:d:', \%opts); } # skip ruby -e '...' calls if(exists($opts{e})) { chdir($cwd); print STDERR "$LOGPREF #$pid: uses no source file (-e), skipping\n" if($self->{debug}); return undef; } # extract source file unless($#ARGV > -1) { chdir($cwd); print STDERR "$LOGPREF #$pid: could not get a source file, skipping\n" if($self->{debug}); return undef; } my $src = abs_path($ARGV[0]); chdir($cwd); unless(-r $src && -f $src) { print STDERR "$LOGPREF #$pid: source file '$src' not found, skipping\n" if($self->{debug}); print STDERR "$LOGPREF #$pid: reduced ARGV: ".join(' ', @ARGV)."\n" if($self->{debug}); return undef; } return $src; } sub files { my $self = shift; my $pid = shift; my $cache = shift; my $ptable = nr_ptable_pid($pid); unless($ptable->{cwd}) { print STDERR "$LOGPREF #$pid: could not get current working directory, skipping\n" if($self->{debug}); return (); } my $cwd = getcwd(); chdir("/proc/$pid/root/$ptable->{cwd}"); # skip the process if the cwd is unreachable (i.e. due to mnt ns) unless(getcwd()) { print STDERR "$LOGPREF #$pid: process cwd is unreachable\n" if($self->{debug}); return (); } # get original ARGV (my $bin, local @ARGV) = nr_parse_cmd($pid); # eat Ruby's command line options my %opts; { local $SIG{__WARN__} = sub { }; getopts('SUacdlnpswvy0:C:E:F:I:K:T:W:e:i:r:x:e:d:', \%opts); } # skip ruby -e '...' calls if(exists($opts{e})) { chdir($cwd); print STDERR "$LOGPREF #$pid: uses no source file (-e), skipping\n" if($self->{debug}); return (); } # extract source file unless($#ARGV > -1) { chdir($cwd); print STDERR "$LOGPREF #$pid: could not get a source file, skipping\n" if($self->{debug}); return (); } my $src = $ARGV[0]; unless(-r $src && -f $src) { chdir($cwd); print STDERR "$LOGPREF #$pid: source file '$src' not found, skipping\n" if($self->{debug}); print STDERR "$LOGPREF #$pid: reduced ARGV: ".join(' ', @ARGV)."\n" if($self->{debug}); return (); } print STDERR "$LOGPREF #$pid: source=$src\n" if($self->{debug}); # use cached data if avail if(exists($cache->{files}->{(__PACKAGE__)}->{$src})) { print STDERR "$LOGPREF #$pid: use cached file list\n" if($self->{debug}); return %{ $cache->{files}->{(__PACKAGE__)}->{$src} }; } # prepare include path environment variable my %e = nr_parse_env($pid); local %ENV; if(exists($e{RUBYLIB})) { $ENV{RUBYLIB} = $e{RUBYLIB}; } elsif(exists($ENV{RUBYLIB})) { delete($ENV{RUBYLIB}); } # get include path my $rbread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'puts $:'); my @path = map { "/proc/$pid/root/$_"; } <$rbread>; close($rbread); chomp(@path); my %files; _scan($self->{debug}, $pid, $src, \%files, \@path); my %ret = map { my $stat = nr_stat("/proc/$pid/root/$_"); $_ => ( defined($stat) ? $stat->{ctime} : undef ); } keys %files; chdir($cwd); $cache->{files}->{(__PACKAGE__)}->{$src} = \%ret; return %ret; } 1; needrestart-3.1/perl/lib/NeedRestart/Kernel.pm000066400000000000000000000103371325725522600214200ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Kernel; use strict; use warnings; use NeedRestart::Utils; use Module::Find; use POSIX qw(uname); use constant { NRK_UNKNOWN => 0, NRK_NOUPGRADE => 1, NRK_ABIUPGRADE => 2, NRK_VERUPGRADE => 3, }; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( nr_kernel_check nr_kernel_vcmp nr_kernel_vcmp_rpm NRK_UNKNOWN NRK_NOUPGRADE NRK_ABIUPGRADE NRK_VERUPGRADE ); my $LOGPREF = '[Kernel]'; sub nr_kernel_check($$) { my $debug = shift; my $ui = shift; my %vars; my ($sysname, $nodename, $release, $version, $machine) = uname; $vars{KVERSION} = $release; print STDERR "$LOGPREF $sysname: kernel release $release, kernel version $version\n" if($debug); # autoload Kernel modules foreach my $module (findsubmod NeedRestart::Kernel) { my @ret; unless(eval "use $module; \@ret = ${module}::nr_kernel_check_real(\$debug, \$ui);") { warn "Failed to load $module: $@" if($@ && $debug); } else { return @ret; } } return (NRK_UNKNOWN, %vars); } ## The following version number comparing stuff was taken from Dpkg::Version. ## The code has been adopted to be usable in needrestart w/o any additional ## dependencies. sub _nr_kversion_order { my ($x) = @_; if ($x eq '~') { return -1; } elsif ($x =~ /^\d$/) { return $x * 1 + 1; } elsif ($x =~ /^[A-Za-z]$/) { return ord($x); } else { return ord($x) + 256; } } sub _nr_kversion_strcmp($$) { my @a = map { _nr_kversion_order($_); } split(//, shift); my @b = map { _nr_kversion_order($_); } split(//, shift); while (1) { my ($a, $b) = (shift @a, shift @b); return 0 unless(defined($a) || defined($b)); $a ||= 0; # Default order for "no character" $b ||= 0; return 1 if($a > $b); return -1 if($a < $b); } } # compare kernel version strings according to Debian's dpkg version scheme sub nr_kernel_vcmp($$) { # sort well known devel tags just as grub does my @v = map { my $v = $_; $v =~ s/[._-](pre|rc|test|git|old|trunk)/~$1/g; $v; } @_; my @a = split(/(?<=\d)(?=\D)|(?<=\D)(?=\d)/, shift(@v)); my @b = split(/(?<=\d)(?=\D)|(?<=\D)(?=\d)/, shift(@v)); while(1) { my ($a, $b) = (shift @a, shift @b); return 0 unless(defined($a) || defined($b)); $a ||= 0; $b ||= 0; if($a =~ /^\d+$/ && $b =~ /^\d+$/) { my $cmp = $a <=> $b; return $cmp if($cmp); } else { my $cmp = _nr_kversion_strcmp($a, $b); return $cmp if($cmp); } } } # compare kernel version strings according to RPM version sorting # adopted from RPM::VersionSort sub nr_kernel_vcmp_rpm { # split version strings by non-alphanumeric digits my @a = split(/[^a-z\d]+/i, shift); my @b = split(/[^a-z\d]+/i, shift); while(1) { my ($a, $b) = (shift @a, shift @b); return 0 unless(defined($a) || defined($b)); # shorter version strings looses (by equal beginning) return 1 unless(defined($b)); return -1 unless(defined($a)); # integer part wins over string part return 1 if($a =~ /^\d/ && $b =~ /^[a-z]/i); return -1 if ($a =~ /^[a-z]/i && $b =~ /^\d/); # compare version parts as int or string if($a =~ /^\d+$/) { my $cmp = $a <=> $b; return $cmp if($cmp); } else { my $cmp = $a cmp $b; return $cmp if($cmp); } } } 1; needrestart-3.1/perl/lib/NeedRestart/Kernel/000077500000000000000000000000001325725522600210565ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart/Kernel/Linux.pm000066400000000000000000000117361325725522600225230ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Kernel::Linux; use strict; use warnings; use NeedRestart::Utils; use NeedRestart::Kernel; use NeedRestart::Strings; use POSIX qw(uname); use Sort::Naturally; use Locale::TextDomain 'needrestart'; use Fcntl qw(SEEK_SET); use constant { NRK_LNX_GETVER_HELPER => q(/usr/lib/needrestart/vmlinuz-get-version), }; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( nr_linux_version_x86 nr_linux_version_generic ); my $LOGPREF = '[Kernel/Linux]'; sub nr_linux_version_x86($$) { my $debug = shift; my $fn = shift; my $fh; unless(open($fh, '<', $fn)) { print STDERR "$LOGPREF Could not open linux image ($fn): $!\n" if($debug); return undef; } binmode($fh); my $buf; # get kernel_version address from header seek($fh, 0x20e, SEEK_SET); read($fh, $buf, 2); my $offset = unpack 'v', $buf; # get kernel_version string seek($fh, 0x200 + $offset, SEEK_SET); read($fh, $buf, 128); close($fh); $buf =~ s/\000.*$//; return undef if($buf eq ''); unless($buf =~ /^\d+\.\d+/) { print STDERR "$LOGPREF Got garbage from linux image header ($fn): '$buf'\n" if($debug); return undef; } return ($buf, 1); } sub nr_linux_version_generic($$) { my $debug = shift; my $fn = shift; # use helper script to get version string if(-x NRK_LNX_GETVER_HELPER) { my $fh = nr_fork_pipe($debug, NRK_LNX_GETVER_HELPER, $fn, $debug); if($fh) { my $verstr = <$fh>; close($fh); if($verstr) { chomp($verstr); return ($verstr, 1) ; } } } else { print STDERR "$LOGPREF ".(NRK_LNX_GETVER_HELPER)." is n/a\n" if($debug); } # fallback trying filename $fn =~ s/[^-]*-//; $fn =~ s/\.img$//; if($fn =~ /^\d+\.\d+/) { print STDERR "$LOGPREF version from filename: $fn\n" if($debug); return ($fn, 0); } return undef; } sub nr_kernel_check_real($$) { my $debug = shift; my $ui = shift; my %vars; my ($sysname, $nodename, $release, $version, $machine) = uname; my $is_x86 = ($machine =~ /^(i\d86|x86_64)$/); $vars{KVERSION} = $release; die "$LOGPREF Not running on Linux!\n" unless($sysname eq 'Linux'); my %kfiles = map { $_ => 1, } grep { # filter initrd images (!m@^/boot/init@); } (, ); $ui->progress_prep(scalar keys %kfiles, __ 'Scanning linux images...'); my %kernels; foreach my $fn (reverse nsort keys %kfiles) { $ui->progress_step; my $stat = nr_stat($fn); unless(defined($stat)) { print STDERR "$LOGPREF could not stat(2) on $fn\n" if($debug); next; } if($stat->{size} < 1000000) { print STDERR "$LOGPREF $fn seems to be too small\n" if($debug); next; } my $verstr; my $abidtc; if($is_x86) { ($verstr, $abidtc) = nr_linux_version_x86($debug, $fn); } unless(defined($verstr)) { ($verstr, $abidtc) = nr_linux_version_generic($debug, $fn); } unless(defined($verstr)) { print STDERR "$LOGPREF Could not get version string from $fn.\n" if($debug); next; } $vars{ABIDETECT} += $abidtc; my $iversion = $verstr; $iversion =~ s/^Linux version //; $iversion =~ s/\s.+$//s; $kernels{$iversion} = (index($verstr, $release) != -1 && index($verstr, $version) != -1); print STDERR "$LOGPREF $fn => $verstr [$iversion]".($kernels{$iversion} ? '*' : '')."\n" if($debug); } $ui->progress_fin; unless(scalar keys %kernels) { print STDERR "$LOGPREF Did not find any linux images.\n" if($debug); return (NRK_UNKNOWN, %vars); } if(-e "/etc/redhat-release" && !-e "/etc/debian_version") { print STDERR "$LOGPREF using RPM version sorting\n" if($debug); ($vars{EVERSION}) = reverse sort { nr_kernel_vcmp_rpm($a, $b); } keys %kernels; } else { ($vars{EVERSION}) = reverse sort { nr_kernel_vcmp($a, $b); } keys %kernels; } print STDERR "$LOGPREF Expected linux version: $vars{EVERSION}\n" if($debug); return (NRK_VERUPGRADE, %vars) if($vars{KVERSION} ne $vars{EVERSION}); return (NRK_ABIUPGRADE, %vars) unless(!$is_x86 || $kernels{$release}); return (NRK_NOUPGRADE, %vars); } 1; needrestart-3.1/perl/lib/NeedRestart/Kernel/kFreeBSD.pm000066400000000000000000000056671325725522600230170ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Kernel::kFreeBSD; use strict; use warnings; use NeedRestart::Utils; use NeedRestart::Kernel; use NeedRestart::Strings; use POSIX qw(uname); use Sort::Naturally; use Locale::TextDomain 'needrestart'; my $LOGPREF = '[Kernel/kFreeBSD]'; sub nr_kernel_check_real($$) { my $debug = shift; my $ui = shift; my %vars; my ($sysname, $nodename, $release, $version, $machine) = uname; $vars{KVERSION} = $release; die "$LOGPREF Not running on GNU/kFreeBSD!\n" unless($sysname eq 'GNU/kFreeBSD'); my @kfiles = reverse nsort ; $ui->progress_prep(scalar @kfiles, __ 'Scanning kfreebsd images...'); my %kernels; foreach my $fn (@kfiles) { $ui->progress_step; my $stat = nr_stat($fn); unless(defined($stat)) { print STDERR "$LOGPREF could not stat(2) on $fn\n" if($debug); next; } if($stat->{size} < 1000000) { print STDERR "$LOGPREF $fn seems to be too small\n" if($debug); next; } my $verstr = nr_strings_fh($debug, qr/FreeBSD \d.+:.+/, nr_fork_pipe($debug, qw(gunzip -c), $fn)); unless(defined($verstr)) { print STDERR "$LOGPREF Could not get version string from $fn.\n" if($debug); next; } my $iversion = $verstr; $iversion =~ s/^.*FreeBSD //; chomp($iversion); $iversion =~ s/\s.+$//; $verstr =~ s/(#\d+):/$1/; $kernels{$iversion} = (index($verstr, $release) != -1 && index($verstr, $version) != -1); print STDERR "$LOGPREF $fn => $verstr [$iversion]".($kernels{$iversion} ? '*' : '')."\n" if($debug); } $ui->progress_fin; unless(scalar keys %kernels) { print STDERR "$LOGPREF Did not find any kfreebsd images (/boot/kfreebsd-*)!\n" if($debug); return (NRK_UNKNOWN, %vars); } ($vars{EVERSION}) = reverse sort { nr_kernel_vcmp($a, $b); } keys %kernels; print STDERR "$LOGPREF Expected kfreebsd version: $vars{EVERSION}\n" if($debug); return (NRK_VERUPGRADE, %vars) if($vars{KVERSION} ne $vars{EVERSION}); return (NRK_ABIUPGRADE, %vars) unless($kernels{$release}); return (NRK_NOUPGRADE, %vars); } 1; needrestart-3.1/perl/lib/NeedRestart/Strings.pm000066400000000000000000000041471325725522600216330ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Strings; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( nr_strings nr_strings_fh ); my $LOGPREF = '[Strings]'; # This strings implementation has been taken from PPT 0.14: # # Copyright 1999 Nathan Scott Thompson # my $PUNCTUATION = join '\\', split //, q/`~!@#$%^&*()-+={}|[]\:";'<>?,.\//; #` my $PRINTABLE = '\w \t' . $PUNCTUATION; my $CHUNKSIZE = 4096; sub nr_strings_fh($$$) { my $debug = shift; my $re = shift; my $fh = shift; binmode($fh); my $offset = 0; while ($_ or read($fh, $_, $CHUNKSIZE)) { $offset += length($1) if(s/^([^$PRINTABLE]+)//o); my $string = ''; do { $string .= $1 if(s/^([$PRINTABLE]+)//o); } until ($_ or !read($fh, $_, $CHUNKSIZE)); if ($string =~ /$re/) { close($fh); return $string; } $offset += length($string); } close($fh); return undef; } sub nr_strings($$$) { my $debug = shift; my $re = shift; my $fn = shift; my $fh; unless(open($fh, '<', $fn)) { print STDERR "$LOGPREF Could not open file ($fn): $!\n" if($debug); return undef; } return nr_strings_fh($debug, $re, $fh); } 1; needrestart-3.1/perl/lib/NeedRestart/UI.pm000066400000000000000000000100261325725522600205100ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::UI; use strict; use warnings; use Text::Wrap qw(wrap $columns); use Term::ReadKey; sub new { my $class = shift; my $verbosity = shift; return bless { verbosity => $verbosity, progress => undef, }, $class; } sub wprint { my $self = shift; my $fh = shift; my $sp1 = shift; my $sp2 = shift; my $message = shift; # only wrap output if it is a terminal if (-t $fh) { # workaround Debian Bug#824564 in Term::ReadKey: pass filehandle twice my ($cols) = GetTerminalSize($fh, $fh); $columns = $cols if($cols); print $fh wrap($sp1, $sp2, $message); } else { print $fh "$sp1$message"; } } sub progress_prep($$$) { my $self = shift; my ($max, $out) = @_; unless(($self->{verbosity} != 1) || !(-t *STDERR)) { # restore terminal if required (debconf) unless(-t *STDIN) { open($self->{fhin}, '<&', \*STDIN) || die "Can't dup stdin: $!\n"; open(STDIN, '< /dev/tty') || open(STDIN, '<&1'); } unless(-t *STDOUT) { open($self->{fhout}, '>&', \*STDOUT) || die "Can't dup stdout: $!\n"; open(STDOUT, '> /dev/tty') || open(STDOUT, '>&2'); } $self->{progress} = { count => 0, max => $max, }; } else { # disable progress indicator while being verbose $self->{progress} = undef; } $self->_progress_msg($out); } sub progress_step($) { my $self = shift; return unless defined($self->{progress}); $self->_progress_inc(); 1; } sub progress_fin($) { my $self = shift; return unless defined($self->{progress}); $self->_progress_fin(); # restore STDIN/STDOUT if required (debconf) open(STDIN, '<&', \*{$self->{fhin}}) || die "Can't dup stdin: $!\n" if($self->{fhin}); open(STDOUT, '>&', \*{$self->{fhout}}) || die "Can't dup stdout: $!\n" if($self->{fhout}); } sub _progress_msg { my $self = shift; return unless defined($self->{progress}); $self->{progress}->{msg} = shift; $self->_progress_out(); } sub _progress_inc { my $self = shift; $self->{progress}->{count}++; $self->_progress_out(); } sub _progress_out { my $self = shift; my ($columns) = GetTerminalSize(\*STDOUT); $columns -= 3; my $wmsg = int($columns * 0.7); $wmsg = length($self->{progress}->{msg}) if(length($self->{progress}->{msg}) < $wmsg); my $wbar = $columns - $wmsg - 1; printf("%-${wmsg}s [%-${wbar}s]\r", substr($self->{progress}->{msg}, 0, $wmsg), '=' x ($wbar*( $self->{progress}->{max} > 0 ? $self->{progress}->{count}/$self->{progress}->{max} : 0 ))); } sub _progress_fin { my $self = shift; $self->{progress}->{count} = 0; my ($columns) = GetTerminalSize(\*STDOUT); print $self->{progress}->{msg}, ' ' x ($columns - length($self->{progress}->{msg})), "\n"; } sub announce_abi { } sub announce_ver { } sub announce_ucode { } sub notice($$) { } sub vspace { my $self = shift; my $fh = shift; print $fh "\n" if(defined($fh)); } sub command() { my $self = shift; $self->notice(@_); } sub query_pkgs($$$$$) { } sub query_conts($$$$$) { } sub runcmd { my $self = shift; my $cb = shift; &$cb; } 1; needrestart-3.1/perl/lib/NeedRestart/UI/000077500000000000000000000000001325725522600201535ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart/UI/Debconf.pm000066400000000000000000000136561325725522600220640ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::UI::Debconf; use strict; use warnings; use parent qw(NeedRestart::UI); use NeedRestart qw(:ui); use Sort::Naturally; use constant { DCTMPL => '/usr/share/needrestart/needrestart.templates', }; BEGIN { die __PACKAGE__." is not supported as normal user!\n" if($<); } use Debconf::Client::ConfModule qw(:all); version('2.0'); capb('backup'); needrestart_ui_register(__PACKAGE__, NEEDRESTART_PRIO_HIGH); sub dcres(@) { return unless(scalar @_); my ($rc, @bulk) = @_; if($rc != 0 && $rc != 30) { stop; die "Debconf: $bulk[0]\n"; } return @bulk; } sub new { my $class = shift; my $verbosity = shift; dcres( x_loadtemplatefile(DCTMPL) ) if(-r DCTMPL); return bless { verbosity => $verbosity, }, $class; } sub _announce { my $self = shift; my $templ = shift; my %vars = @_; foreach my $k (keys %vars) { dcres( subst($templ, $k, $vars{$k}) ); } dcres( fset($templ, 'seen', 0) ); dcres( settitle('needrestart/ui-kernel_title') ); dcres( input('critical', $templ) ); dcres( go ); } sub announce_abi { my $self = shift; $self->_announce('needrestart/ui-kernel_announce_abi', @_); } sub announce_ver { my $self = shift; $self->_announce('needrestart/ui-kernel_announce_ver', @_); } sub announce_ehint { my $self = shift; my %vars = @_; my $templ = q(needrestart/ui-ehint_announce); foreach my $k (keys %vars) { dcres( subst($templ, $k, $vars{$k}) ); } dcres( fset($templ, 'seen', 0) ); dcres( settitle('needrestart/ui-ehint_title') ); dcres( input('critical', $templ) ); dcres( go ); } sub announce_ucode { my $self = shift; my %vars = @_; my $templ = 'needrestart/ui-ucode_announce'; foreach my $k (keys %vars) { dcres( subst($templ, $k, $vars{$k}) ); } dcres( fset($templ, 'seen', 0) ); dcres( settitle('needrestart/ui-ucode_title') ); dcres( input('critical', $templ) ); dcres( go ); } sub notice { my $self = shift; my $out = shift; return unless($self->{verbosity}); my $indent = ' '; $indent .= $1 if($out =~ /^(\s+)/); $self->wprint(\*STDERR, '', $indent, "$out\n"); } sub vspace { my $self = shift; return unless($self->{verbosity}); $self->SUPER::vspace(\*STDERR); } sub command { my $self = shift; my $out = shift; print STDERR "$out\n"; } sub query_pkgs($$$$$$) { my $self = shift; my $out = shift; my $defno = shift; my $pkgs = shift; my $overrides = shift; my $cb = shift; # prepare checklist array my @l = nsort keys %$pkgs; # apply rc selection overrides my @selected = (); foreach my $pkg (@l) { my $found; foreach my $re (keys %$overrides) { next unless($pkg =~ /$re/); push(@selected, $pkg) if($overrides->{$re}); $found++; last; } push(@selected, $pkg) unless($defno || $found); } dcres(set('needrestart/ui-query_pkgs', join(', ', @selected))); dcres( subst('needrestart/ui-query_pkgs', 'OUT', $out) ); dcres( subst('needrestart/ui-query_pkgs', 'PKGS', join(', ', @l)) ); dcres( fset('needrestart/ui-query_pkgs', 'seen', 0) ); dcres( settitle('needrestart/ui-query_pkgs_title') ); dcres( input('critical', 'needrestart/ui-query_pkgs') ); my ($r) = dcres( go ); my ($s) = dcres( get('needrestart/ui-query_pkgs') ); # user has canceled return unless(defined($s)); return if($r eq 'backup'); # get selected rc.d script my @s = split(/, /, $s); $self->runcmd(sub { # restart each selected service script &$cb($_) for @s; }); } sub query_conts($$$$$$) { my $self = shift; my $out = shift; my $defno = shift; my $pkgs = shift; my $overrides = shift; my $cb = shift; # prepare checklist array my @l = nsort keys %$pkgs; # apply rc selection overrides my @selected = (); foreach my $pkg (@l) { my $found; foreach my $re (keys %$overrides) { next unless($pkg =~ /$re/); push(@selected, $pkg) if($overrides->{$re}); $found++; last; } push(@selected, $pkg) unless($defno || $found); } dcres(set('needrestart/ui-query_conts', join(', ', @selected))); dcres( subst('needrestart/ui-query_conts', 'OUT', $out) ); dcres( subst('needrestart/ui-query_conts', 'CONTS', join(', ', @l)) ); dcres( fset('needrestart/ui-query_conts', 'seen', 0) ); dcres( settitle('needrestart/ui-query_conts_title') ); dcres( input('critical', 'needrestart/ui-query_conts') ); my ($r) = dcres( go ); my ($s) = dcres( get('needrestart/ui-query_conts') ); # user has canceled return unless(defined($s)); return if($r eq 'backup'); # get selected rc.d script my @s = split(/, /, $s); $self->runcmd(sub { # restart each selected service script &$cb($_) for @s; }); } sub runcmd { my $self = shift; local *STDOUT; # Debconf kills STDOUT... try to restore it open(STDOUT, '> /dev/tty') || open(STDOUT, '>&2'); $self->SUPER::runcmd(@_); close(STDOUT); } 1; needrestart-3.1/perl/lib/NeedRestart/UI/stdio.pm000066400000000000000000000115171325725522600216400ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::UI::stdio; use strict; use warnings; use parent qw(NeedRestart::UI); use NeedRestart qw(:ui); use Locale::TextDomain 'needrestart'; needrestart_ui_register(__PACKAGE__, NEEDRESTART_PRIO_LOW); sub _announce { my $self = shift; my $message = shift; my %vars = @_; print "\n"; $self->wprint(\*STDOUT, '', '', __x("Pending kernel upgrade!\n\nRunning kernel version:\n {kversion}\n\nDiagnostics:\n {message}\n\nRestarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. [Return]\n", kversion => $vars{KVERSION}, message => $message, )); if (-t *STDIN && -t *STDOUT); } sub announce_abi { my $self = shift; my %vars = @_; $self->_announce(__ 'The currently running kernel has an ABI compatible upgrade pending.', %vars); } sub announce_ver { my $self = shift; my %vars = @_; $self->_announce(__x("The currently running kernel version is not the expected kernel version {eversion}.", eversion => $vars{EVERSION}, ), %vars); } sub announce_ehint { my $self = shift; my %vars = @_; $self->wprint(\*STDOUT, '', '', __x(< $vars{EHINT})); This system runs {ehint}. For more details, run «needrestart -m a». You should consider rebooting! EHINT if (-t *STDIN && -t *STDOUT); } sub announce_ucode { my $self = shift; my %vars = @_; print "\n"; $self->wprint(\*STDOUT, '', '', __x("Pending processor microcode upgrade!\n\nDiagnostics:\n The currently running processor microcode revision is {current} which is not the expected microcode revision {avail}.\n\nRestarting the system to load the new processor microcode will not be handled automatically, so you should consider rebooting. [Return]\n", current => $vars{CURRENT}, avail => $vars{AVAIL}, )); if (-t *STDIN && -t *STDOUT); } sub notice($$) { my $self = shift; my $out = shift; return unless($self->{verbosity}); my $indent = ' '; $indent .= $1 if($out =~ /^(\s+)/); $self->wprint(\*STDOUT, '', $indent, "$out\n"); } sub vspace { my $self = shift; return unless($self->{verbosity}); $self->SUPER::vspace(\*STDOUT); } sub command { my $self = shift; my $out = shift; print "$out\n"; } sub _query($$) { my $self = shift; my($query, $def) = @_; my @def = ($def eq 'Y' ? qw(yes no auto stop) : qw(no yes auto stop)); my $i; do { $self->wprint(\*STDOUT, '', '', "$query [" . ($def eq 'Y' ? 'Ynas?' : 'yNas?') . '] '); if($self->{stdio_same}) { my $s = $self->{stdio_same}; if($s eq 'auto') { $s = ($def eq 'Y' ? 'yes' : 'no'); } print __($s), "\n"; return $s; } $i = if(-t *STDIN && -t *STDOUT); unless(defined($i)) { $i = 'n'; last; } $i = lc($i); chomp($i); $i =~ s/^\s+//; $i =~ s/\s+$//; if($i eq '?') { $self->wprint(\*STDOUT, '', '', __ <{stdio_same} = 'auto'; return ($def eq 'Y' ? q(yes) : q(no)); } return ($self->{stdio_same} = 'no') if($i eq 'stop'); return $i; } sub query_pkgs($$$$$$) { my $self = shift; my $out = shift; my $def = shift; my $pkgs = shift; my $overrides = shift; my $cb = shift; delete($self->{stdio_same}); $self->wprint(\*STDOUT, '', '', "$out\n"); foreach my $rc (sort keys %$pkgs) { my ($or) = grep { $rc =~ /$_/; } keys %$overrides; my $d = (defined($or) ? ($overrides->{$or} ? 'Y' : 'N') : ($def ? 'N' : 'Y')); &$cb($rc) if($self->_query(__x('Restart «{rc}»?', rc => $rc), $d) eq 'yes'); } } sub query_conts($$$$$$) { my $self = shift; $self->query_pkgs(@_); } 1; needrestart-3.1/perl/lib/NeedRestart/Utils.pm000066400000000000000000000073621325725522600213040ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::Utils; use strict; use warnings; use Proc::ProcessTable; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( nr_ptable nr_ptable_pid nr_parse_cmd nr_parse_env nr_readlink nr_stat nr_fork_pipe nr_fork_pipe_stderr nr_fork_pipew nr_fork_pipe2 ); my %ptable = map {$_->pid => $_} @{ new Proc::ProcessTable(enable_ttys => 1)->table }; sub nr_ptable() { return \%ptable; } sub nr_ptable_pid($) { my $pid = shift; return $ptable{$pid}; } sub nr_parse_cmd($) { my $pid = shift; my $fh; open($fh, '<', "/proc/$pid/cmdline") || return (); local $/ = "\000"; my @cmdline = <$fh>; chomp(@cmdline); close($fh); return @cmdline; } sub nr_parse_env($) { my $pid = shift; my $fh; open($fh, '<', "/proc/$pid/environ") || return (); local $/ = "\000"; my @env = <$fh>; chomp(@env); close($fh); return map { (/^([^=]+)=(.*)$/ ? ($1, $2) : ()) } @env; } my %readlink; sub nr_readlink($) { my $pid = shift; return $readlink{$pid} if(exists($readlink{$pid})); my $fn = "/proc/$pid/exe"; return ($readlink{$pid} = readlink($fn)); } my %stat; sub nr_stat($) { my $fn = shift; return $stat{$fn} if(exists($stat{$fn})); my @stat = stat($fn); return undef unless($#stat > -1); $stat{$fn} = { dev => $stat[0], ino => $stat[1], mode => $stat[2], nlink => $stat[3], uid => $stat[4], gid => $stat[5], rdev => $stat[6], size => $stat[7], atime => $stat[8], mtime => $stat[9], ctime => $stat[10], blksize => $stat[11], blocks => $stat[12], }; return $stat{$fn}; } sub nr_fork_pipe($@) { my $debug = shift; my $pid = open(HPIPE, '-|'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { close(STDIN); close(STDERR) unless($debug); undef $ENV{LANG}; exec(@_); exit; } \*HPIPE } sub nr_fork_pipe_stderr { my $debug = shift; my $pid = open(HPIPE, '-|'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { open(STDERR, '>&', STDOUT) || die "Can't dup stderr: $!\n"; close(STDIN); undef $ENV{LANG}; exec(@_); exit; } \*HPIPE } sub nr_fork_pipew($@) { my $debug = shift; my $pid = open(HPIPE, '|-'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { close(STDOUT); close(STDERR) unless($debug); undef $ENV{LANG}; exec(@_); exit; } \*HPIPE } sub nr_fork_pipe2($@) { my $debug = shift; my ($pread, $fhwrite); pipe($pread, $fhwrite) || die "Can't pipe: $!\n"; my $fhread; my $pid = open($fhread, '-|'); defined($pid) || die "Can't fork: $!\n"; if($pid == 0) { open(STDIN, '<&', $pread) || die "Can't dup stdin: $!\n"; close(STDERR) unless($debug); undef $ENV{LANG}; exec(@_); exit; } close($pread); return ($fhread, $fhwrite); } 1; needrestart-3.1/perl/lib/NeedRestart/uCode.pm000066400000000000000000000044041325725522600212350ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::uCode; use strict; use warnings; use NeedRestart::Utils; use Module::Find; use Locale::TextDomain 'needrestart'; use constant { NRM_UNKNOWN => 0, NRM_CURRENT => 1, NRM_OBSOLETE => 2, }; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( nr_ucode_check NRM_UNKNOWN NRM_CURRENT NRM_OBSOLETE ); my $LOGPREF = '[ucode]'; my @PKGS; sub nr_ucode_check { my $debug = shift; my $ui = shift; # autoload ucode modules foreach my $module (findsubmod NeedRestart::uCode) { unless(eval "use $module; ${module}::nr_ucode_init(\$debug);") { warn "Failed to load $module: $@" if($@ && $debug); } else { push(@PKGS, $module); } } unless(scalar @PKGS > 0) { print STDERR "$LOGPREF no supported processor microcode detection\n" if($debug); return (NRM_UNKNOWN, ()); } $ui->progress_prep(scalar @PKGS, __ 'Scanning processor microcode...'); # autoload ucode modules my ($state, @vars) = (NRM_UNKNOWN); foreach my $pkg (@PKGS) { eval "(\$state, \@vars) = ${pkg}::nr_ucode_check_real(\$debug, \$ui);"; $ui->progress_step; if($state == NRM_OBSOLETE) { $ui->progress_fin; return ($state, @vars) } } $ui->progress_fin; return ($state, @vars); } 1; needrestart-3.1/perl/lib/NeedRestart/uCode/000077500000000000000000000000001325725522600206755ustar00rootroot00000000000000needrestart-3.1/perl/lib/NeedRestart/uCode/Intel.pm000066400000000000000000000053601325725522600223120ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2018 (C) Thomas Liske [http://fiasko-nw.net/~thomas/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # package NeedRestart::uCode::Intel; use strict; use warnings; use NeedRestart::uCode; use NeedRestart::Utils; use POSIX qw(uname); use Sort::Naturally; use Locale::TextDomain 'needrestart'; use constant { NRM_INTEL_HELPER => q(/usr/lib/needrestart/iucode-scan-versions), }; my $LOGPREF = '[uCode/Intel]'; sub nr_ucode_init { my ($sysname, $nodename, $release, $version, $machine) = uname; my $is_x86 = ($machine =~ /^(i\d86|x86_64)$/); die "$LOGPREF Not running on x86!\n" unless($is_x86); die "$LOGPREF iucode-tool not available!\n" unless(`which iucode_tool`); } sub nr_ucode_check_real { my $debug = shift; my $ui = shift; my %vars; # get current microcode revision if(open(my $fh, '<', '/proc/cpuinfo')) { while (<$fh>) { if (/^microcode\s+:\s+(0x[\da-f]+)/i) { $vars{CURRENT} = sprintf("0x%x", hex($1)); last; } } close($fh); } else { print STDERR "$LOGPREF unable to open /proc/cpuinfo: $!\n" if($debug); return (NRM_UNKNOWN, %vars); } my $fh = nr_fork_pipe($debug, NRM_INTEL_HELPER, $debug); while(<$fh>) { if (/\s+\d+\/\d+: sig.+, rev (0x[\da-f]+),/) { $vars{AVAIL} = sprintf("0x%x", hex($1)); print STDERR "$LOGPREF available revision: $1\n" if($debug); next; } } close($fh); unless(exists($vars{CURRENT}) && exists($vars{AVAIL})) { print STDERR "$LOGPREF did not get current microcode version\n" if($debug && !exists($vars{CURRENT})); print STDERR "$LOGPREF did not get available microcode version\n" if($debug && !exists($vars{AVAIL})); return (NRM_UNKNOWN, %vars); } if($vars{CURRENT} eq $vars{AVAIL}) { return (NRM_CURRENT, %vars); } return (NRM_OBSOLETE, %vars); } 1; needrestart-3.1/po/000077500000000000000000000000001325725522600143245ustar00rootroot00000000000000needrestart-3.1/po/debconf000077700000000000000000000000001325725522600204322../ex/debconf/poustar00rootroot00000000000000needrestart-3.1/po/needrestart-notify/000077500000000000000000000000001325725522600201525ustar00rootroot00000000000000needrestart-3.1/po/needrestart-notify/Makefile000066400000000000000000000004741325725522600216170ustar00rootroot00000000000000TEXTDOMAIN:=needrestart-notify all: for po in $(wildcard *.po); do \ lang=$$(basename -s .po $$po); \ mkdir -p ../.build/$$lang/LC_MESSAGES; \ msgfmt -o ../.build/$$lang/LC_MESSAGES/$(TEXTDOMAIN).mo $$po; \ done merge: for po in $(wildcard *.po); do \ msgmerge -U $$po messages.pot; \ done needrestart-3.1/po/needrestart-notify/de.po000066400000000000000000000033171325725522600211060ustar00rootroot00000000000000#, fuzzy msgid "" msgstr "" "Project-Id-Version: needrestart-notify 2.7\n" "Report-Msgid-Bugs-To: thomas@fiasko-nw.net\n" "POT-Creation-Date: 2016-02-28 19:33+0100\n" "PO-Revision-Date: 2016-03-05 11:11+0100\n" "Last-Translator: Thomas Liske \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ex/notify.d/200-write:32 msgid "" "Your session is running obsolete binaries or libraries as listed below.\n" "Please consider a relogin or restart of the affected processes!" msgstr "" "In dieser Sitzung laufen die im Folgenden aufgelisteten veralteten Prozesse.\n" "Bitte ziehen Sie eine Neuanmeldung oder den Neustart betroffener Anwendungen in Betracht!" #: ex/notify.d/600-mail:41 #, sh-format msgid "" "Your session on host $_NR_FQDN ($NR_SESSION) is running obsolete binaries or " "libraries as listed below." msgstr "" "In der Sitzung $NR_SESSION auf dem Host $_NR_FQDN laufen die im Folgenden aufgelisteten veralteten Prozesse." #: ex/notify.d/600-mail:44 msgid "Please consider a relogin or restart of the affected processes!" msgstr "Bitte ziehen Sie eine Neuanmeldung oder den Neustart betroffener Anwendungen in Betracht!" #: ex/notify.d/400-notify-send:44 msgid "Relogin or restarts required!" msgstr "Neuanmeldung oder Neustart nötig!" #: ex/notify.d/400-notify-send:45 msgid "" "Your session is running obsolete binaries or libraries as listed below.\n" "Please consider a relogin or restart of the affected processes!" msgstr "" "In dieser Sitzung laufen die im Folgenden aufgelisteten veralteten Prozesse.\n" "Bitte ziehen Sie eine Neuanmeldung oder den Neustart betroffener Anwendungen in Betracht!" needrestart-3.1/po/needrestart-notify/messages.pot000066400000000000000000000025471325725522600225150ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the needrestart-notify package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: needrestart-notify 2.12\n" "Report-Msgid-Bugs-To: thomas@fiasko-nw.net\n" "POT-Creation-Date: 2018-02-11 13:55+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ex/notify.d/200-write:32 msgid "" "Your session is running obsolete binaries or libraries as listed below.\n" "Please consider a relogin or restart of the affected processes!" msgstr "" #: ex/notify.d/600-mail:41 #, sh-format msgid "" "Your session on host $_NR_FQDN ($NR_SESSION) is running obsolete binaries or " "libraries as listed below." msgstr "" #: ex/notify.d/600-mail:44 msgid "Please consider a relogin or restart of the affected processes!" msgstr "" #: ex/notify.d/400-notify-send:44 msgid "Relogin or restarts required!" msgstr "" #: ex/notify.d/400-notify-send:45 msgid "" "Your session is running obsolete binaries or libraries as listed below.\n" "Please consider a relogin or restart of the affected processes!" msgstr "" needrestart-3.1/po/needrestart-notify/ru.po000066400000000000000000000047701325725522600211500ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016 # This file is distributed under the same license as the needrestart package. # Vladimir Kudrya # msgid "" msgstr "" "Project-Id-Version: needrestart-notify 2.7\n" "Report-Msgid-Bugs-To: thomas@fiasko-nw.net\n" "POT-Creation-Date: 2016-06-04 08:44+0300\n" "PO-Revision-Date: 2016-06-04 08:48+0300\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.7.1\n" "Last-Translator: Vladimir Kudrya \n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "Language: ru\n" #: ex/notify.d/200-write:32 msgid "" "Your session is running obsolete binaries or libraries as listed below.\n" "Please consider a relogin or restart of the affected processes!" msgstr "" "В вашем сеансе выполняются устаревшие процессы или библиотеки, перечисленные " "ниже.\n" "Запланируйте повторный вход в систему, или перезапустите указанные процессы!" #: ex/notify.d/600-mail:41 #, sh-format msgid "" "Your session on host $_NR_FQDN ($NR_SESSION) is running obsolete binaries or " "libraries as listed below." msgstr "" "В вашем сеансе на хосте $_NR_FQDN ($NR_SESSION) запущены устаревшие процессы " "или библиотеки, перечисленные ниже." #: ex/notify.d/600-mail:44 msgid "Please consider a relogin or restart of the affected processes!" msgstr "" "Запланируйте повторный вход в систему, или перезапустите указанные процессы!" #: ex/notify.d/400-notify-send:44 msgid "Relogin or restarts required!" msgstr "Требуется повторный вход или перезапуск процессов!" #: ex/notify.d/400-notify-send:45 msgid "" "Your session is running obsolete binaries or libraries as listed below.\n" "Please consider a relogin or restart of the affected processes!" msgstr "" "В вашем сеансе выполняются устаревшие процессы или библиотеки, перечисленные " "ниже.\n" "Запланируйте повторный вход в систему, или перезапустите указанные " "процессы!" needrestart-3.1/po/needrestart/000077500000000000000000000000001325725522600166445ustar00rootroot00000000000000needrestart-3.1/po/needrestart/Makefile000066400000000000000000000004651325725522600203110ustar00rootroot00000000000000TEXTDOMAIN:=needrestart all: for po in $(wildcard *.po); do \ lang=$$(basename -s .po $$po); \ mkdir -p ../.build/$$lang/LC_MESSAGES; \ msgfmt -o ../.build/$$lang/LC_MESSAGES/$(TEXTDOMAIN).mo $$po; \ done merge: for po in $(wildcard *.po); do \ msgmerge -U $$po messages.pot; \ done needrestart-3.1/po/needrestart/de.po000066400000000000000000000150611325725522600175770ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: needrestart 2.8\n" "Report-Msgid-Bugs-To: thomas@fiasko-nw.net\n" "POT-Creation-Date: 2018-03-29 13:45+0200\n" "PO-Revision-Date: 2018-02-11 15:10+0100\n" "Last-Translator: Thomas Liske \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: needrestart:234 msgid "Available UI packages:" msgstr "Verfügbare Oberflächen:" #: needrestart:438 msgid "Scanning processes..." msgstr "Prüfe Prozesse..." #: needrestart:584 msgid "Scanning candidates..." msgstr "Prüfe Kandidaten..." #: needrestart:758 msgid "Your outdated processes:" msgstr "Veraltete Prozesse:" #: needrestart:822 msgid "Running kernel seems to be up-to-date." msgstr "Der laufende Kernel ist aktuell." #: needrestart:822 msgid "Running kernel seems to be up-to-date (ABI upgrades are not detected)." msgstr "" "Der laufende Kernel ist aktuell (ABI Änderungen können nicht erkannt werden)." #: needrestart:826 needrestart:840 msgid "an outdated kernel image" msgstr "eine veraltete Kernel-Version" #: needrestart:831 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} and there is an ABI " "compatible upgrade pending." msgstr "" "Die aktuelle Kernel-Version ist {kversion} und es ist ein ABI-kompatibles " "Upgrade ausstehend." #: needrestart:845 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} which is not the expected " "kernel version {eversion}." msgstr "" "Die aktuelle Kernel-Version ist {kversion} was nicht die erwartete Version " "{eversion} ist." #: needrestart:856 msgid "Failed to retrieve available kernel versions." msgstr "Fehler beim Ermitteln der verfügbaren Kernel-Versionen." #: needrestart:895 msgid "The processor microcode seems to be up-to-date." msgstr "Der Prozessor Mikrocode ist aktuell." #: needrestart:899 msgid "outdated processor microcode" msgstr "veralteter Prozesse Mikrocode" #: needrestart:907 msgid "Failed to check for processor microcode upgrades." msgstr "Fehler beim Ermitteln von verfügbaren Prozessor Mikrocode-Upgrades." #: needrestart:916 msgid "No services need to be restarted." msgstr "Es müssen keine Dienste neugestartet werden." #: needrestart:925 msgid "outdated binaries" msgstr "veraltete Programme" #: needrestart:931 needrestart:1041 msgid "Services to be restarted:" msgstr "Dienste, die neu gestartet werden müssen:" #: needrestart:932 needrestart:1040 msgid "Restarting services..." msgstr "Dienste werden neu gestartet..." #: needrestart:995 needrestart:1067 msgid "Service restarts being deferred:" msgstr "Dienste deren Neustart verschoben wurde:" #: needrestart:1010 needrestart:1081 msgid "Service restarts being refused by systemd:" msgstr "Dienste die durch systemd nicht neu gestartet werden:" #: needrestart:1095 msgid "No containers need to be restarted." msgstr "Es müssen keine Container neu gestartet werden." #: needrestart:1104 msgid "outdated containers" msgstr "veraltete Containern" #: needrestart:1109 needrestart:1161 msgid "Containers to be restarted:" msgstr "Container, die neu gestartet werden müssen:" #: needrestart:1110 needrestart:1160 msgid "Restarting containers..." msgstr "Neustart von Containern..." #: needrestart:1151 msgid "Container restarts being deferred:" msgstr "Container deren Neustart verschoben wurde:" #: needrestart:1174 msgid "No user sessions are running outdated binaries." msgstr "Es gibt keine Nutzer-Sitzungen mit veralteten Prozessen." #: needrestart:1183 msgid "outdated sessions" msgstr "veraltete Sitzungen" #: needrestart:1186 msgid "User sessions running outdated binaries:" msgstr "Nutzer-Sitzungen mit veralteten Prozessen:" #: needrestart:1234 msgid "and" msgstr "und" #: perl/lib/NeedRestart/Kernel/Linux.pm:136 msgid "Scanning linux images..." msgstr "Prüfe Linux-Kernel..." #: perl/lib/NeedRestart/Kernel/kFreeBSD.pm:49 msgid "Scanning kfreebsd images..." msgstr "Prüfe kFreeBSD-Kernel..." #: perl/lib/NeedRestart/UI/stdio.pm:42 #, perl-brace-format msgid "" "Pending kernel upgrade!\n" "\n" "Running kernel version:\n" " {kversion}\n" "\n" "Diagnostics:\n" " {message}\n" "\n" "Restarting the system to load the new kernel will not be handled " "automatically, so you should consider rebooting. [Return]\n" msgstr "" "Ausstehendes Kernel-Upgrade!\n" "\n" "Laufende Kernel-Version:\n" " {kversion}\n" "\n" "Diagnose:\n" " {message}\n" "\n" "Das System wird nicht automatisch neu gestartet um den neuen Kernel zu " "laden. Ein Neustart sollte durchgeführt werden. [Return]\n" #: perl/lib/NeedRestart/UI/stdio.pm:54 msgid "The currently running kernel has an ABI compatible upgrade pending." msgstr "Für den laufende Kernel ist ein ABI-kompatibles Upgrade ausstehend." #: perl/lib/NeedRestart/UI/stdio.pm:62 #, perl-brace-format msgid "" "The currently running kernel version is not the expected kernel version " "{eversion}." msgstr "" "Die aktuelle Kernel-Version ist nicht die erwartete Version {eversion}." #: perl/lib/NeedRestart/UI/stdio.pm:73 #, perl-brace-format msgid "" "\n" "This system runs {ehint}. For more details, run «needrestart -m a».\n" "\n" "You should consider rebooting!\n" "\n" msgstr "" "\n" "Das System verwendet {ehint}. Der Befehl »needrestart -m a« zeigt mehr " "Details.\n" "\n" "Ein Neustart sollte durchgeführt werden!\n" "\n" #: perl/lib/NeedRestart/UI/stdio.pm:89 #, perl-brace-format msgid "" "Pending processor microcode upgrade!\n" "\n" "Diagnostics:\n" " The currently running processor microcode revision is {current} which is " "not the expected microcode revision {avail}.\n" "\n" "Restarting the system to load the new processor microcode will not be " "handled automatically, so you should consider rebooting. [Return]\n" msgstr "" "Ausstehendes Prozessor Mikrocode-Upgrade!\n" "\n" "Diagnose:\n" " Die aktuelle Prozessor Mikrocode-Revision ist {current} statt der " "erwarteten Mikrocode-Revision {avail}.\n" "\n" "Das System wird nicht automatisch neu gestartet um den Prozessor Mikrocode " "zu laden. Ein Neustart sollte durchgeführt werden. [Return]\n" #: perl/lib/NeedRestart/UI/stdio.pm:156 msgid "" " (Y)es - restart this service\n" " (N)o - do not restart this service\n" " (A)uto - auto restart all remaining services\n" " (S)top - stop restarting services\n" "\n" msgstr "" " ja (Y) - diesen Dienst neu starten\n" " (N)ein - diesen Dienst nicht neu starten\n" " (A)uto - alle weiteren Dienste automatisch neu starten\n" " (S)top - keine weiteren Dienste neu starten\n" "\n" #: perl/lib/NeedRestart/UI/stdio.pm:189 #, perl-brace-format msgid "Restart «{rc}»?" msgstr "»{rc}« neu starten?" needrestart-3.1/po/needrestart/messages.pot000066400000000000000000000110511325725522600211750ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the needrestart package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: needrestart 2.12\n" "Report-Msgid-Bugs-To: thomas@fiasko-nw.net\n" "POT-Creation-Date: 2018-03-29 13:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: needrestart:234 msgid "Available UI packages:" msgstr "" #: needrestart:438 msgid "Scanning processes..." msgstr "" #: needrestart:584 msgid "Scanning candidates..." msgstr "" #: needrestart:758 msgid "Your outdated processes:" msgstr "" #: needrestart:822 msgid "Running kernel seems to be up-to-date." msgstr "" #: needrestart:822 msgid "Running kernel seems to be up-to-date (ABI upgrades are not detected)." msgstr "" #: needrestart:826 needrestart:840 msgid "an outdated kernel image" msgstr "" #: needrestart:831 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} and there is an ABI " "compatible upgrade pending." msgstr "" #: needrestart:845 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} which is not the expected " "kernel version {eversion}." msgstr "" #: needrestart:856 msgid "Failed to retrieve available kernel versions." msgstr "" #: needrestart:895 msgid "The processor microcode seems to be up-to-date." msgstr "" #: needrestart:899 msgid "outdated processor microcode" msgstr "" #: needrestart:907 msgid "Failed to check for processor microcode upgrades." msgstr "" #: needrestart:916 msgid "No services need to be restarted." msgstr "" #: needrestart:925 msgid "outdated binaries" msgstr "" #: needrestart:931 needrestart:1041 msgid "Services to be restarted:" msgstr "" #: needrestart:932 needrestart:1040 msgid "Restarting services..." msgstr "" #: needrestart:995 needrestart:1067 msgid "Service restarts being deferred:" msgstr "" #: needrestart:1010 needrestart:1081 msgid "Service restarts being refused by systemd:" msgstr "" #: needrestart:1095 msgid "No containers need to be restarted." msgstr "" #: needrestart:1104 msgid "outdated containers" msgstr "" #: needrestart:1109 needrestart:1161 msgid "Containers to be restarted:" msgstr "" #: needrestart:1110 needrestart:1160 msgid "Restarting containers..." msgstr "" #: needrestart:1151 msgid "Container restarts being deferred:" msgstr "" #: needrestart:1174 msgid "No user sessions are running outdated binaries." msgstr "" #: needrestart:1183 msgid "outdated sessions" msgstr "" #: needrestart:1186 msgid "User sessions running outdated binaries:" msgstr "" #: needrestart:1234 msgid "and" msgstr "" #: perl/lib/NeedRestart/Kernel/Linux.pm:136 msgid "Scanning linux images..." msgstr "" #: perl/lib/NeedRestart/Kernel/kFreeBSD.pm:49 msgid "Scanning kfreebsd images..." msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:42 #, perl-brace-format msgid "" "Pending kernel upgrade!\n" "\n" "Running kernel version:\n" " {kversion}\n" "\n" "Diagnostics:\n" " {message}\n" "\n" "Restarting the system to load the new kernel will not be handled " "automatically, so you should consider rebooting. [Return]\n" msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:54 msgid "The currently running kernel has an ABI compatible upgrade pending." msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:62 #, perl-brace-format msgid "" "The currently running kernel version is not the expected kernel version " "{eversion}." msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:73 #, perl-brace-format msgid "" "\n" "This system runs {ehint}. For more details, run «needrestart -m a».\n" "\n" "You should consider rebooting!\n" "\n" msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:89 #, perl-brace-format msgid "" "Pending processor microcode upgrade!\n" "\n" "Diagnostics:\n" " The currently running processor microcode revision is {current} which is " "not the expected microcode revision {avail}.\n" "\n" "Restarting the system to load the new processor microcode will not be " "handled automatically, so you should consider rebooting. [Return]\n" msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:156 msgid "" " (Y)es - restart this service\n" " (N)o - do not restart this service\n" " (A)uto - auto restart all remaining services\n" " (S)top - stop restarting services\n" "\n" msgstr "" #: perl/lib/NeedRestart/UI/stdio.pm:189 #, perl-brace-format msgid "Restart «{rc}»?" msgstr "" needrestart-3.1/po/needrestart/ru.po000066400000000000000000000145701325725522600176410ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: needrestart 2.8\n" "Report-Msgid-Bugs-To: thomas@fiasko-nw.net\n" "POT-Creation-Date: 2016-06-11 10:32+0300\n" "PO-Revision-Date: 2016-06-11 11:09+0300\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.8\n" "Last-Translator: Vladimir Kudrya \n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "Language: ru\n" #: needrestart:350 msgid "Scanning processes..." msgstr "Сканирование процессов..." #: needrestart:486 msgid "Scanning candidates..." msgstr "Сканирование кандидатов..." #: needrestart:660 msgid "Your outdated processes:" msgstr "Устаревшие процессы:" #: needrestart:710 msgid "Running kernel seems to be up-to-date." msgstr "Запущено ядро последней версии." #: needrestart:710 msgid "Running kernel seems to be up-to-date (ABI upgrades are not detected)." msgstr "Запущено ядро последней версии (обновлений ABI не найдено)." #: needrestart:714 needrestart:727 msgid "an outdated kernel image" msgstr "устаревший образ ядра" #: needrestart:718 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} and there is an ABI " "compatible upgrade pending." msgstr "" "Версия текущего запущенного ядра: {kversion}, незавершенное обновление ABI в " "процессе." #: needrestart:731 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} which is not the expected " "kernel version {eversion}." msgstr "" "Версия текущего запущенного ядра {kversion} не совпадает с ожидаемой версией " "{eversion}." #: needrestart:741 msgid "Failed to retrieve available kernel versions." msgstr "Невозможно получить доступные версии ядра." #: needrestart:750 msgid "No services need to be restarted." msgstr "Службы не требуют перезапуска." #: needrestart:759 msgid "outdated binaries" msgstr "устаревшие процессы" #: needrestart:764 needrestart:829 msgid "Services to be restarted:" msgstr "Службы на перезапуск:" #: needrestart:765 needrestart:828 msgid "Restarting services..." msgstr "Перезапуск служб..." #: needrestart:812 needrestart:856 msgid "Service restarts being deferred:" msgstr "Пропущенные службы:" #: needrestart:875 msgid "No containers need to be restarted." msgstr "Контейнеры не требуют перезапуска." #: needrestart:884 msgid "outdated containers" msgstr "устаревшие контейнеры" #: needrestart:889 needrestart:934 msgid "Containers to be restarted:" msgstr "Контейнеры на перезапуск:" #: needrestart:890 needrestart:933 msgid "Restarting containers..." msgstr "Перезапуск контейнеров..." #: needrestart:924 msgid "Container restarts being deferred:" msgstr "Пропущенные контейнеры:" #: needrestart:946 msgid "No user sessions are running outdated binaries." msgstr "В сеансах пользователей нет устаревших процессов." #: needrestart:955 msgid "outdated sessions" msgstr "устаревшие сеансы" #: needrestart:958 msgid "User sessions running outdated binaries:" msgstr "Сеансы пользователей с устаревшими процессами:" #: needrestart:998 msgid "and" msgstr "и" #: perl/lib/NeedRestart/Kernel/Linux.pm:129 msgid "Scanning linux images..." msgstr "Сканироване образов linux..." #: perl/lib/NeedRestart/Kernel/kFreeBSD.pm:49 msgid "Scanning kfreebsd images..." msgstr "Сканирование образов kfreebsd..." #: perl/lib/NeedRestart/UI/stdio.pm:41 #, perl-brace-format msgid "" "Pending kernel upgrade!\n" "\n" "Running kernel version:\n" " {kversion}\n" "\n" "Diagnostics:\n" " {message}\n" "\n" "Restarting the system to load the new kernel will not be handled " "automatically, so you should consider rebooting. [Return]\n" msgstr "" "Незавершенное обновление ядра!\n" "\n" "Версия текущего ядра:\n" " {kversion}\n" "\n" "Диагностика:\n" " {message}\n" "\n" "Перезагрузка системы для запуска нового ядра не будет выполнена " "автоматически, поэтому запланируйте перезагрузку. [Return]\n" #: perl/lib/NeedRestart/UI/stdio.pm:53 msgid "The currently running kernel has an ABI compatible upgrade pending." msgstr "Для текущего ядра есть незавершенное обновление ABI." #: perl/lib/NeedRestart/UI/stdio.pm:61 #, perl-brace-format msgid "" "The currently running kernel version is not the expected kernel version " "{eversion}." msgstr "Запущенное ядро не соответствует ожидаемой версии {eversion}." #: perl/lib/NeedRestart/UI/stdio.pm:72 #, perl-brace-format msgid "" "\n" "This system runs {ehint}. For more details, run «needrestart -m a».\n" "\n" "You should consider rebooting!\n" "\n" msgstr "" "\n" "В системе запущено: {ehint}. Для получения подробностей выполните " "«needrestart -m a».\n" "\n" "Запланируйте перезагрузку!\n" "\n" #: perl/lib/NeedRestart/UI/stdio.pm:104 msgid "yes" msgstr "да" #: perl/lib/NeedRestart/UI/stdio.pm:104 msgid "no" msgstr "нет" #: perl/lib/NeedRestart/UI/stdio.pm:126 msgid "" " (Y)es - restart this service\n" " (N)o - do not restart this service\n" " (A)uto - auto restart all remaining services\n" " (S)top - stop restarting services\n" "\n" msgstr "" " (Y)es - перезапустить службу\n" " (N)o - не перезапускать службу\n" " (A)uto - автоматически перезапустить оставшиеся службы\n" " (S)top - прекратить перезапуск служб\n" "\n" #: perl/lib/NeedRestart/UI/stdio.pm:159 #, perl-brace-format msgid "Restart «{rc}»?" msgstr "Перезапустить «{rc}»?"