pax_global_header00006660000000000000000000000064147770062540014526gustar00rootroot0000000000000052 comment=6d7a76b065dc82386f3e10a77f4cb1bca853804b needrestart-3.11/000077500000000000000000000000001477700625400137725ustar00rootroot00000000000000needrestart-3.11/.github/000077500000000000000000000000001477700625400153325ustar00rootroot00000000000000needrestart-3.11/.github/no-response.yml000066400000000000000000000012641477700625400203300ustar00rootroot00000000000000# Configuration for probot-no-response - https://github.com/probot/no-response # Number of days of inactivity before an Issue is closed for lack of response daysUntilClose: 14 # Label requiring a response responseRequiredLabel: moreinfo # Comment to post when closing an Issue for lack of response. Set to `false` to disable closeComment: > This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further. needrestart-3.11/.gitignore000066400000000000000000000001741477700625400157640ustar00rootroot00000000000000autom4te.cache/ debian/ man/Makefile perl/MYMETA.json perl/MYMETA.yml perl/Makefile perl/blib/ perl/pm_to_blib po/.build *~ needrestart-3.11/AUTHORS000066400000000000000000000000751477700625400150440ustar00rootroot00000000000000needrestart =========== Thomas Liske needrestart-3.11/COPYING000066400000000000000000000432541477700625400150350ustar00rootroot00000000000000 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 Lesser 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 Lesser General Public License instead of this License. needrestart-3.11/ChangeLog000066400000000000000000001235411477700625400155520ustar00rootroot00000000000000needrestart 3.11 * Changes: - [CONT] allow to ignore containers by name (github issue #260 by Arnaud Rebillout @elboulangero) - [Kernel] allow glob customization for find kernel image files (github issue #297 by @tblancher) * Fixes: - [core] fix warnings if no cgroup could be determined (github issue #339 by Aristarkh Zagorodnikov @onyxmaster) -- Thomas Liske Sun, 13 Apr 2025 21:07:19 +0200 needrestart 3.10 * Changes: - [core] add override for systemd-nspawn (Debian Bug #1101553) (Debian Bug#1101553 by Raphaël Halimi ) - [core] add another pattern to ignore java native access (github issue #267 by @rdemongeot) * Fixes: - [core] unbreak systemd-user w/ dash (Debian Bug#1101551 by Raphaël Halimi ) (github pull request #338 by Ivan Shapovalov @intelfx) - [metrics] fix undefined values warning if no expected ucode version is available -- Thomas Liske Sun, 06 Apr 2025 12:52:14 +0200 needrestart 3.9 * Features: - [CONT] Detect systemd-nspawn and add a fallback module. (github pull request #302 by Ivan Shapovalov @intelfx) - [Core] Add option '-x' to skip user interaction when no process is selected for restart by default. (github pull request #336 by @larsen0815) * Changes: - [Core] Add default override for qrtr-ns / rmtfs. (github pull request #332 by Arnaud Ferraris @a-wai) - [Core] Add override for bacula. (Debian Bug#1017417 by Carsten Leonhardt ) - [Core] Add override for lxc. (Debian Bug#1030843 by Richard Hector ) - [Core] Add override for xrdp. (Debian Bug#1042008 by Andrew Chadwick ) - [Core] Print executable in verbose mode. (github issue #277 by Paul Wise @pabs3) - [Core] Better systemd --user integration. (github pull request #301 by Ivan Shapovalov @intelfx) - [Core] Ignore /memfd: binaries. (github issue #283 by @flisk) (github issue #287 by @moerkey) - [Docs] Update kernel naming in config example for RPi2/3. (github pull request #330 by @Popkornium18) - [Docs] Document -b a little more. (github pull request #333 by @flisk) - [L10N] Add zh-TW Traditional Chinese locale. (github pull request #320 by Peter Dave Hello @PeterDaveHello) * Fixes: - [Core] Fix regression of false positives for processes running in chroot or mountns (#317). (github issue #317 by Ivan Kurnosov @zerkms) - [Core] Fix typos. (github pull request #335 by Viktor Szépe @szepeviktor) - [Docs] Fix missing escapes in markdown files. (github issue #312 by Mikko Rantalainen @mikkorantalainen) - [Interp] Fix source file scanning for processes in another mountns. (github pull request #327 by Corey Hickey @bugfood) - [uCode] Do not print undef values in batch mode. (github issue #322 by @guruguruguru) -- Thomas Liske Thu, 27 Mar 2025 22:55:21 +0100 needrestart 3.8 * Security: - [Core] CVE-2024-48991: Prevent race condition on /proc/$PID/exec evaluation. (responsibly reported by Qualys) - [Interp] CVE-2024-11003: Drop usage of Module::ScanDeps to prevent LPE. (responsibly reported by Qualys) - [Interp] CVE-2024-48990: Do not set PYTHONPATH environment variable to prevent a LPE. (responsibly reported by Qualys) - [Interp] CVE-2024-48992: Do not set RUBYLIB environment variable to prevent a LPE. (responsibly reported by Qualys) * Features: - [CONT] Add Incus support. (github pull request #315 by Colin Watson @cjwatson) * Changes: - [Core] Refactor device number comparison to be independent of leading zeros. (closes #286) - [Interp] Enable ruby check for versioned ruby binary names. (suggested by Qualys) - [Interp] Chdir into empty directory to prevent python parsing arbitrary files. (motivated by Qualys) * Fixes: - [VM] Fix spelling mistake. (github pull request #309 by @fritz-fritz) - [Core] Make OpenMetrics output prometheus compatible. (github pull request #311 by Gabriel Filion @lelutin) - [uCode] Fix error handling logic being dependent on debug level. (github pull request #313 by Aristarkh Zagorodnikov @onyxmaster) - [Core] Fix "Use of uninitialized value $sdev in right bitshift". (github pull request #314 by Aristarkh Zagorodnikov @onyxmaster) This release contains some critical security fixes in the interpreter module. While the default configuration was vulnerable it is possible to mitigate the issues by disabling the interpreter heuristic: `$nrconf{interpscan} = 0;` All CVEs received a CVSS core of: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H [7.8 HIGH] Qualys Security Advisory: https://www.qualys.com/2024/11/19/needrestart/needrestart.txt Many thanks to the Qualys Security Advisory team and Mark Esler from the Ubuntu Security Team for the responsible disclosure, reviewing patches and coordinating the disclosure of these security issues. -- Thomas Liske Tue, 19 Nov 2024 17:00:00 +0100 needrestart 3.7 * Features: - [Interp] Add optional persistent cache support for perl scanning. (github pull request #282 by Jean-Marc Saffroy @saffroy) - [Core] Add OpenMetrics time series output. (github pull request #308 by Gabriel Filion @lelutin) * Changes: - [Core] Replace `which` by `command -v`. (github pull request #254 by @a1346054) - [Core] Ignore USBGuard. (github pull request #257 by Christoph Anton Mitterer @calestyo) - [Core] Do not ignore dhclient but prevent restart ifup automatically. (github pull request #262 by @anarcat) - [Core] Add greetd to the list of restart exclusions. (github pull request #266 by Iván Zaera @ivan-zaera) - [Core] Support dbus replacements. (github pull request #276 by @Vladimir-csp) - [Core] Apply override_rc deterministically. (github pull request #280 by Corey Hickey @bugfood) - [uCode] Test vendor id before check for Intel ucode. (github pull request #284 by FRITZ|FRITZ @fritz-fritz) - [uCode] Fix AMD ucode checking in non-debug mode. (github pull request #288 by @anarcat) - [uCode] Mark unavailable ucode as CURRENT. (github pull request #290 by @anarcat) - [Kernel] Increase read size for version strings. (github pull request #293 by @jaycci) - [README] Add RPi5 details. (github pull request #298 by @Opa-) - [README] Add RPi1 details. (github pull request #304 by @juadde) - [uCode] Add an option to print uCode hints w/o acknowledgement. (github pull request #307 by Adam @adsr) * Fixes: - [README] Prevent shell expansion in example. (github pull request #252 by David Taylor @dtaylor84) - [Core] Fix VM detection regression introduced in f54d85c. (github pull request #248 by @zxyrepf) - [uCode] Fix uninitialized value regression. (github pull request #273 by Stefan Bühler @stbuehler) - [uCode] Fix AMD uCode check in non-debug mode. (github pull request #278 by Jan-Philipp Litza @jplitza) - [CONT] Fix always ignoring lxc/lxd instances. (github issue #245 by Mitsuya Shibata @m-shibata) - [Core] Fix shellcheck issues. (github issue #300 by Eisuke Kawashima @e-kwsm) - [Kernel] Fix kernel version detection for kernel images >= 6.0. (github issue #245 by Stefan Bühler @tik-stbuehler) -- Thomas Liske Sun, 11 Aug 2024 22:59:32 +0200 needrestart 3.6 * Security: - [Interp] CVE-2022-30688: Anchor interpreter regex to prevent local privilege escalation. (responsibly reported by Jakub Wilk) * Features: - [Core] Add support for runit. (Debian Bug#972685 by Lorenzo Puliti ) - [VM] Add support to detect outdated VM processes (i.e. qemu). (github pull request #216 by Christian Ehrhardt @cpaelzer) * Changes: - [Cont] Improve LXD container support. (github pull request #188 by James TD Smith @ahktenzero) - [Cont] Update cgroup regex for LXC 4.0. (github pull request #215 by James TD Smith @ahktenzero) - [Cont] Support cgroup v2 for docker. (github pull request #234 by Markus Frosch @lazyfrosch) - [Cont] Support cgroup v2 for LXC/LXD. (github pull request #238 by Trent Lloyd @lathiat) - [Core] Support cgroup v2 for services and user sessions. - [Core] Support systemd manager restart on Ubuntu 20.04+. (github pull request #195 by Lars Kollstedt @LarsKollstedt) - [Core] Do not restart bluetooth.service by default. (github pull request #209 by Erik Tews @eriktews) - [Core] Do not restart elogind by default. (github issue #205 by @HumanG33k) - [Core] Output user sessions in batch mode. (github pull request #232 by @anarcat) - [Core] Use ImVirt for virtualization detection if not running on systemd. (Debian Bug#984789 by Patrik Schindler ) - [Interp] Add tolerance when checking script file ctimes to avoid false positives. (github pull request #233 by Corey Hickey @bugfood) - [Kernel] Replace strings(1) by GNU grep to drop binutils dependency. (Debian Bug#986507 by Trent W. Buck ) * Fixes: - [Core] Fix comment for default value of `skip_mapfiles`. (github pull request #179 by @iasdeoupxe) - [Interp] Fix detection for ruby script started from relative paths. (github pull request #182 by Alexander Neumann @rtpt-alex) - [Core] Fix typos. (github pull request #189 by @wwuck) (github pull request #193 by Stefan Weil @stweil) - [Core] Fix verbose/verbosity confusion in needrestart.conf. (github pull request #197 by Jan-Philipp Litza @jplitza) - [Core] Ignore memfd files like used by nvidia's binary drivers. (github pull request #200 by Jan Visser @starquake) - [Core] Ignore all memfd mappings. (Debian Bug#972685 by Michail Bachmann ) - [Core] Ignore Java Native Access mappings. (github issue #142 by @nirgal) (github issue #185 by Ivan Zaera @izaera) - [Core] nagios: Do not print perfdata data in unknown state. (github pull request #222 by Lorenz @RincewindsHat) - [uCode] Fix 'uninitialized value' on AMD. (github pull request #226 by Christian Garbs @mmitch) * Misc: - Minor cleanups (whitespaces, shellcheck, ...). (github pull request #217 by @a1346054) - Update README.batch.md. (github pull request #219 by Stavros Ntentos @stdedos) - Add icinga2 example config. (github pull request #223 by Lorenz @RincewindsHat) - [uCode] Fix lsinitrd example. (github pull request #240 by Corey Hickey @bugfood) -- Thomas Liske Tue, 17 May 2022 17:00:00 +0200 needrestart 3.5 * Features: - [uCode] Check for pending AMD microcode updates (experimental). (Debian Bug#886611 by Paul Wise ) (github issue #150 by Tom Reynolds @tomreyn and Mark Wagie @yochananmarqos) * Changes: - [Core] Add network.service to blacklist. (github pull request #145 by Marc Dequènes (Duck) @duck-rh) - [uCode] Check microcode revision of each individual CPUs. - [Kernel] Support kernel image filename filtering required for Raspbian. (github issue #146 by @takichikawa) (github issue #155 by Fenhl @fenhl and Christian @git-developer) - [uCode] Support local override for iucode_tool call. (github issue #148 by @mphilipps and Marc Dequènes (Duck) @duck-rh) - [notify] Add app name to notify-send call. (github issue #76 by @Vladimir-csp) * Fixes: - [Core] Do not restart networking.service. (Debian Bug#922725 by Timo Sigurdsson ). - [Core] Fix typo in man page for env variable DEBIAN_FRONT(END). (Debian Bug#922864 by Lee Garrett ) (Debian Bug#923853 by Petter Reinholdtsen ) - [Interp] Restore cwd when skipping processes with unavailable cwd. (github issue #147 by Stavros Ntentos @stdedos) - [Core] Remove leading zero before testing in map_files. (Debian Bug#928225 by Alexander Galanin ) - [Core] Fix typos in ex/needrestart.conf. (github pull request #163 by Simon Brand @brandsimon) - [UI] Don't fail when terminal has zero columns width. (github pull request #167 by @libnoon) - [Core] Ignore mapped files not found on filesystem (stat) to suppress chroot false positives. (github issue #158 by @mphilipps) (github issue #152 by Ivan Kurnosov @zerkms and @djl) - [Core] Suppress warnings from Proc::ProcessTable. (github issue #170 by @mphilipps) - [CONT] Fix docker detection on CentOS 7. (github issue #165 by Christian Ruppert @idl0r) - [notify] Fix notify-send not working with dbus-user-session. (github issue #76 by @Vladimir-csp) - [Core] Ignore mapped files in temporary directories. (Debian Bug#925408 by Donald Pellegrino ) -- Thomas Liske Sun, 22 Mar 2020 17:36:57 +0100 needrestart 3.4 * Features: - [L10n] Add Czech localization. (github pull request #131 by @p-bo) (github pull request #132 by @p-bo) (github pull request #133 by @p-bo) - [Core] Add FRR to override. (github pull request #138 by David Lamparter @eqvinox) - [Core] Detect if run inside a container or vm using systemd. (github issue #139 by Tobby @tobby88) - [Core] Skip needrestart in apt hook if system is shutting down. (Debian Bug#914753 by Balint Reczey ) * Changes: - [Core] Do restart systemd-journald (again). (see also Debian Bug#771122, #771254 and #898818) (Debian Bug#898818 by Mathieu Parent ) * Fixes: - [uCode] Ignore broken microcode files (required for CentOS). (github issue #123 by Marc Dequènes (Duck) @duck-rh) - [uCode] Parse output of old iucode-tool 1.5. (github pull request #127 by Lutz Heermann @LuHee) - [uCode] Prevent microcode false positives for BIOS updates. (Debian Bug#906958 by Maik Zumstrull ) - [uCode] Handle microcode updates for multiple CPUs in initramfs. (Debian Bug#907372 by Paul Wise ) - [Core] Ignore temporary mappings of elasticsearch. (github issue #134 by Georg @teadur) - [Core] Do not restart oneshot services from systemd-cron. (Debian Bug#917073 by Antti Salmela ) -- Thomas Liske Tue, 05 Feb 2019 22:43:12 +0100 needrestart 3.3 * Fixes: - [Core] Configuration file is ignored. (Debian Bug#901999 by Andreas Schmidt ) (Debian Bug#902031 by Axel Beckert ) (Debian Bug#902049 by Jon ) (github issue #121 by Sven Hartge @shartge) - [Interp] Suppress uninitialized value if abs_path fails. (github issue #120 by Craig Andrews @candrews) -- Thomas Liske Sun, 24 Jun 2018 13:32:47 +0200 needrestart 3.2 * Changes: - [Kernel] Include /boot/kernel* while looking for linux kernel images (required for Gentoo) (Gentoo Bug 654958 by Klaus Ethgen) (github pull request #113 by Craig Andrews @candrews) - [Core] Do not restart ModemManager by default. (github pull request #119 by @bodqhrohro) * Fixes: - [UI] Do not call GetTerminalSize if STDOUT is not a tty. (github pull request #110 by Michael Scherer @mscherer) - [uCode] Filter microcode for CPU signature and flags. (github issue #112 by @mgondium) (Debian Bug#900298 by Francois Mescam ) - [uCode] Assigning ucodehints a false value disables ucode checks. (github issue #115 by Johannes Kampmeyer @xschlef) - [Hooks] Ignore non-executable init scripts. (github issue #116 by Marc Dequènes (Duck) @duck-rh) - [L10n] Fix typo in Russian localization. (github pull request #118 by @bodqhrohro) - [UI] Do not leak fd into restarted services. (Debian Bug#893152 by Stephen Rothwell ) -- Thomas Liske Sat, 16 Jun 2018 17:42:51 +0200 needrestart 3.1 * 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 * 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 formatting. (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 * 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 * Features: - [Interp] Allow ignoring of interpreted files. (github issue #39 by Wolfgang Karall @wolfgangkarall) - [Core] Make verification of mapped files in filesystem 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 * 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 * 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 "Unknown 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 * [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 globally (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 * [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 * [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 * [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 * [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 * [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 * [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 * [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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 children (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 * 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 * Initial release. -- Thomas Liske Fri, 29 Mar 2013 19:40:09 +0100 needrestart-3.11/INSTALL.md000066400000000000000000000004771477700625400154320ustar00rootroot00000000000000Prerequisites ============= Perl ---- - Module::Find - Locale::TextDomain - Proc::ProcessTable - Sort::Naturally - Term::ReadKey - Parent (for legacy Perl versions, i.e. on CentOS 6) - ImVirt (optional; highly recommended if not running on systemd) Misc ---- - gettext - po-debconf (on Debian derivates) - xz-utils needrestart-3.11/Makefile000066400000000000000000000055621477700625400154420ustar00rootroot00000000000000LOCALEDIR=/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/" cp ex/iucode.sh "$(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/" command -v 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 command -v 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)/" mkdir -p "$(DESTDIR)/var/cache/needrestart" 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.11/NEWS000066400000000000000000000057471477700625400145060ustar00rootroot00000000000000Changes 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. Therefore 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.11/README.Cont.md000066400000000000000000000024631477700625400161600ustar00rootroot00000000000000needrestart - 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/*` || `/lxc.payload/*`) For each container which should be restarted needrestart calls `lxc-stop --reboot --name $NAME`. This package also supports LXD containers, which are restarted by `lxc restart $NAME` or `lxc restart --project=$PROJECT $NAME` for containers in projects, and Incus containers, which are restarted by `incus restart $NAME` or `incus restart --project=$PROJECT $NAME` for containers in projects. 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.11/README.Interp.md000066400000000000000000000046321477700625400165160ustar00rootroot00000000000000needrestart - 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 The source file is scanned only for 'use' lines, other module loading mechanisms will not be recognized. *This function used the Module::ScanDeps package to get the used Perl packages until needrestart 3.7. Module::ScanDeps is not used any more as it seems not to be designed to work with untrustworthy perl sources which would allow an attacker to use needrestart for local privilege escalation.* 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.11/README.batch.md000066400000000000000000000016401477700625400163320ustar00rootroot00000000000000needrestart - 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 NEEDRESTART-SESS: metabase @ user manager service NEEDRESTART-SESS: root @ session #28017 ``` 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 compliant with 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.11/README.md000066400000000000000000000060331477700625400152530ustar00rootroot00000000000000needrestart =========== 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 traditional System V init script. Frontends --------- *needrestart* uses a modular approach 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. Since *needrestart* 3.5 it is possible to filter kernel image filenames (required on [Raspberry Pi](README.raspberry.md)). In *needrestart* 3.0 a [processor microcode update detection feature](README.uCode.md) for Intel CPUs has been added. Since *needrestart* 3.5 the AMD CPU support 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.11/README.nagios.md000066400000000000000000000014211477700625400165260ustar00rootroot00000000000000needrestart - 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.11/README.raspberry.md000066400000000000000000000027351477700625400172700ustar00rootroot00000000000000needrestart - Raspberry Pi ========================== Raspbian and other linux distros are installing multiple kernel images in parallel: - `kernel.img` - `kernel7.img` - `kernel7l.img` - `kernel8.img` This might result in a continuous pending kernel update false positive. There is a configuration option in needrestart to filter the kernel image filenames to ignore the unused image files. ### RPi 1 or RPi 1B ```shell $ cat << 'EOF' > /etc/needrestart/conf.d/kernel.conf # Filter kernel image filenames by regex. This is required on Raspian having # multiple kernel image variants installed in parallel. $nrconf{kernelfilter} = qr(vmlinuz-.*-v6$); EOF ``` ### RPi 2 or RPi 3 ```shell $ cat << 'EOF' > /etc/needrestart/conf.d/kernel.conf # Filter kernel image filenames by regex. This is required on Raspian having # multiple kernel image variants installed in parallel. $nrconf{kernelfilter} = qr(vmlinuz-.*-v7$); EOF ``` ### RPi 5 RPi 5 has the ability to switch between 16KB and 4KB page size kernels. Run `uname -r` to get the currently used kernel. By default, it should be `6.1.0-rpi8-rpi-2712` (16KB page size). ```shell $ cat << 'EOF' > /etc/needrestart/conf.d/kernel.conf # Filter kernel image filenames by regex. This is required on Raspian having # multiple kernel image variants installed in parallel. # 6.1.0-rpi8-rpi-v8 (4KB page size) # $nrconf{kernelfilter} = qr(vmlinuz-.*-v8$); # 6.1.0-rpi8-rpi-2712 (16KB page size) $nrconf{kernelfilter} = qr(vmlinuz-.*-2712$); EOF ``` needrestart-3.11/README.uCode.md000066400000000000000000000017061477700625400163130ustar00rootroot00000000000000needrestart - 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 AMD and Intel CPUs. AMD --- Needrestart decodes the AMD ucode firmware files to check for updates. This requires to know the cpu's CPUID value. The most reliable way is to use the cpuid kernel module (modprobe cpuid). As a fallback the CPUID is calculated from /proc/cpuinfo. The calculation might be wrong and should be avoided by loading the cpuinfo kernel module. 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.11/ex/000077500000000000000000000000001477700625400144065ustar00rootroot00000000000000needrestart-3.11/ex/99needrestart000066400000000000000000000005511477700625400170340ustar00rootroot00000000000000# 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.11/ex/apt/000077500000000000000000000000001477700625400151725ustar00rootroot00000000000000needrestart-3.11/ex/apt/apt-pinvoke000077500000000000000000000030231477700625400173530ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 # check if system is shutting down, see also Debian Bug#914753 if [ -d '/run/systemd/system' ]; then sd=$(dbus-send --system --dest=org.freedesktop.login1 \ --print-reply \ /org/freedesktop/login1 \ org.freedesktop.DBus.Properties.Get \ string:org.freedesktop.login1.Manager \ string:PreparingForShutdown 2> /dev/null) if [ "$sd" != "${sd% true}" ]; then echo "skipping needrestart since system is preparing for shutdown" exit 0 fi fi 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.11/ex/apt/dpkg-status000077500000000000000000000020171477700625400173660ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 -r tag p0 p1 p2 p3 p4 pp; do if [ "$tag" = 'status:' ] && [ "$p1" = 'unpacked' ]; then if [ "$touched" = 0 ]; then touch "$RUNDIR/unpacked" touched=1 fi else if [ "$tag" = 'status:' ] && \ [ "$p1" = ':' ] && \ [ "$p2" = 'error' ] && \ [ "$p3" = ':' ]; then if [ "$errored" = 0 ]; then touch "$RUNDIR/errored" errored=1 fi fi fi done needrestart-3.11/ex/apt/needrestart-apt_d000066400000000000000000000005221477700625400205210ustar00rootroot00000000000000# 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.11/ex/apt/needrestart-dpkg_d000066400000000000000000000004221477700625400206610ustar00rootroot00000000000000# 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.11/ex/conf.d/000077500000000000000000000000001477700625400155555ustar00rootroot00000000000000needrestart-3.11/ex/conf.d/README.needrestart000066400000000000000000000003611477700625400207540ustar00rootroot00000000000000Files 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.11/ex/debconf/000077500000000000000000000000001477700625400160065ustar00rootroot00000000000000needrestart-3.11/ex/debconf/needrestart.templates000066400000000000000000000035201477700625400222460ustar00rootroot00000000000000Template: 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.11/ex/debconf/po/000077500000000000000000000000001477700625400164245ustar00rootroot00000000000000needrestart-3.11/ex/debconf/po/POTFILES.in000066400000000000000000000001021477700625400201720ustar00rootroot00000000000000[encoding: UTF-8] [type: gettext/rfc822deb] needrestart.templates needrestart-3.11/ex/debconf/po/cs.po000066400000000000000000000100131477700625400173640ustar00rootroot00000000000000# 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. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-03-29 13:45+0200\n" "PO-Revision-Date: 2018-09-26 11:10+0200\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 2.0.6\n" "Last-Translator: \n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "Language: cs\n" #. Type: title #. Description #: ../needrestart.templates:1001 msgid "Daemons using outdated libraries" msgstr "Procesy služeb, které používají zastaralé knihovny" #. Type: multiselect #. Description #: ../needrestart.templates:2001 msgid "Which services should be restarted?" msgstr "Které služby by měly být restartovány?" #. Type: note #. Description #. Type: note #. Description #: ../needrestart.templates:3001 ../needrestart.templates:4001 msgid "Newer kernel available" msgstr "Je k dispozici novější verze jádra" #. Type: note #. Description #: ../needrestart.templates:3001 msgid "" "The currently running kernel version is ${KVERSION} and there is an ABI " "compatible upgrade pending." msgstr "" "Nyní je provozováno na jádru verze ${KVERSION} a přitom je k dispozici " "aktualizace, která zachovává kompatibilní ABI rozhraní." #. 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 "" "Restart systému pro načtení nového jádra nebude obsloužen automaticky, " "takže byste měli zvážit restart stroje." #. Type: note #. Description #: ../needrestart.templates:4001 msgid "" "The currently running kernel version is ${KVERSION} which is not the " "expected kernel version ${EVERSION}." msgstr "" "Nyní provozovaná verze jádra je ${KVERSION}, což není očekávaná verze " "${EVERSION}." #. Type: title #. Description #: ../needrestart.templates:5001 msgid "Pending kernel upgrade" msgstr "Čekající aktualizace jádra" #. Type: title #. Description #: ../needrestart.templates:6001 msgid "Restart pending..." msgstr "Čekající restart…" #. Type: note #. Description #: ../needrestart.templates:7001 msgid "This system runs ${EHINT} - you should consider rebooting!" msgstr "Tento systém je spuštěný s ${EHINT} – měli byste zvážit restart!" #. Type: note #. Description #: ../needrestart.templates:7001 msgid "For more details, run «needrestart -m a»." msgstr "Další informace získáte spuštěním „needrestart -m a“." #. Type: title #. Description #: ../needrestart.templates:8001 msgid "Outdated processor microcode" msgstr "Zastaralý mikrokód procesoru" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "Processor microcode update" msgstr "Aktualizace mikrokódu procesoru" #. Type: note #. Description #: ../needrestart.templates:9001 msgid "" "The currently running processor microcode revision is ${CURRENT} which is " "not the expected microcode revision ${AVAIL}." msgstr "" "Nyní provozovaná revize mikrokódu procesoru je ${CURRENT}, což není " "očekávaná revize ${AVAIL}." #. 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 "" "Restart systému pro načtení nového mikrokódu procesoru nebude obsloužen " "automaticky, takže byste měli zvážit restart stroje." #. Type: title #. Description #: ../needrestart.templates:10001 msgid "Containers using outdated libraries" msgstr "Kontejnery používající zastaralé knihovny" #. Type: multiselect #. Description #: ../needrestart.templates:11001 msgid "Which containers should be restarted?" msgstr "Které kontejnery by měly být restartovány?" needrestart-3.11/ex/debconf/po/de.po000066400000000000000000000076261477700625400173670ustar00rootroot00000000000000# 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} erwartet." #. 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.11/ex/debconf/po/ru.po000066400000000000000000000065401477700625400174170ustar00rootroot00000000000000msgid "" 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.11/ex/debconf/po/templates.pot000066400000000000000000000056431477700625400211560ustar00rootroot00000000000000# 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.11/ex/debconf/po/zh_TW.po000066400000000000000000000073751477700625400200330ustar00rootroot00000000000000# Traditional Chinese translation for needrestart. # Copyright (C) 2024 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the needrestart package. # Peter Dave Hello , 2024. # 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: 2024-11-22 19:26+0800\n" "Last-Translator: Peter Dave Hello \n" "Language-Team: Traditional Chinese\n" "Language: zh_TW\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 "目前運作中的核心版本為 ${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 "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 "目前執行中的處理器微碼版本為 ${CURRENT},與預期微碼版本 ${AVAIL} 不符。" #. 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.11/ex/icinga2/000077500000000000000000000000001477700625400157225ustar00rootroot00000000000000needrestart-3.11/ex/icinga2/command.conf000066400000000000000000000006221477700625400202070ustar00rootroot00000000000000object CheckCommand "needrestart" { command = [ "/usr/sbin/needrestart", "-p" ] arguments = { "-k" = { description = "check for obsolete kernel" set_if = "$needrestart_kernel$" } "-l" = { description = "check for obsolete libraries" set_if = "$needrestart_libraries$" } "-w" = { description = "check for obsolete CPU microcode" set_if = "$needrestart_microcode$" } } } needrestart-3.11/ex/icinga2/needrestart-sudoers000066400000000000000000000007341477700625400216530ustar00rootroot00000000000000# 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 on debian based systems (icinga user is called "nagios") nagios ALL=NOPASSWD: /usr/sbin/needrestart # Allow nagios to execute the needrestart command on centos and family (icinga user is called "icinga") icinga ALL=NOPASSWD: /usr/sbin/needrestart needrestart-3.11/ex/iucode.sh000066400000000000000000000012121477700625400162060ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # This shell script is sourced in /usr/lib/needrestart/iucode-scan-versions # before calling iucode_tool to detect microcode updates for Intel CPUs. # # If required you may exec iucode_tool with customized parameters. You should # keep the `-l $filter` option and add a final exit statement in case the # exec call fails. # Example (generic): # exec iucode_tool -l $filter --ignore-broken -tb /lib/firmware/intel-ucode -ta /usr/share/misc/intel-microcode* 2>&1 # exit $? # Example (RHEL and derivatives): # lsinitrd -f kernel/x86/microcode/GenuineIntel.bin | iucode_tool -t b -l - # exit $? needrestart-3.11/ex/nagios/000077500000000000000000000000001477700625400156665ustar00rootroot00000000000000needrestart-3.11/ex/nagios/check_needrestart000077500000000000000000000007761477700625400213030ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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.11/ex/nagios/needrestart-nagios000066400000000000000000000004241477700625400214070ustar00rootroot00000000000000# 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.11/ex/nagios/plugin.conf000066400000000000000000000005671477700625400200430ustar00rootroot00000000000000## 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.11/ex/needrestart.conf000066400000000000000000000153331477700625400176020ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # This is the configuration file of needrestart. This is perl syntax. # needrestart 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 apt-get (Debian Bug#784237) qr(^/usr/bin/apt-get(\.dpkg-new)?$), # ignore memfd mappings (github issue #283, #287) qr(^/memfd:), ]; # Blacklist containers by name (list of regex). $nrconf{blacklist_cont} = [ # ignore containers like ci-017-222a371c #qr(^ci-), ]; # Blacklist services (list of regex) - USE WITH CARE. # You should prefer to put services to $nrconf{override_rc} instead. # Any service listed in $nrconf{blacklist_rc} will be ignored completely! #$nrconf{blacklist_rc} = [ #]; # Override service default selection (hash of regex). # Regexes are checked in lexical order; the first matching regex will be used. $nrconf{override_rc} = { # DBus qr(^dbus) => 0, # display managers qr(^gdm) => 0, qr(^greetd) => 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, qr(^xrdp) => 0, # networking stuff qr(^bird) => 0, qr(^network) => 0, qr(^NetworkManager) => 0, qr(^ModemManager) => 0, qr(^wpa_supplicant) => 0, qr(^ifup) => 0, qr(^openvpn) => 0, qr(^quagga) => 0, qr(^frr) => 0, qr(^tinc) => 0, qr(^(open|free|libre|strong)swan) => 0, qr(^bluetooth) => 0, # gettys qr(^getty@.+\.service) => 0, # systemd --user qr(^user@\d+\.service) => 0, # misc qr(^usbguard\.service$) => 0, qr(^zfs-fuse) => 0, qr(^mythtv-backend) => 0, qr(^xendomains) => 0, qr(^lxc) => 0, qr(^lxcfs) => 0, qr(^libvirt) => 0, qr(^virtlogd) => 0, qr(^virtlockd) => 0, qr(^docker) => 0, qr(^bacula-) => 0, # see Debian bugs #1095222 & #1095223 qr(^qrtr-ns) => 0, qr(^rmtfs) => 0, # systemd stuff # (see also Debian Bug#784238 & #784437) qr(^emergency\.service$) => 0, qr(^rescue\.service$) => 0, qr(^elogind) => 0, # do not restart oneshot services, see also #862840 qr(^apt-daily\.service$) => 0, qr(^apt-daily-upgrade\.service$) => 0, qr(^unattended-upgrades\.service$) => 0, # do not restart oneshot services from systemd-cron, see also #917073 qr(^cron-.*\.service$) => 0, # ignore rc-local.service, see #852864 qr(^rc-local\.service$) => 0, # don't restart systemd-logind, see #798097 qr(^systemd-logind) => 0, # don't restart systemd-nspawn containers (Debian Bug #1101553) qr(^systemd-nspawn) => 0, }; # Override container default selection (hash of regex). $nrconf{override_cont} = { }; # Disable interpreter scanners. #$nrconf{interpscan} = 0; # Use a persistent cache file of perl scanning results #$nrconf{perlcache} = "/var/cache/needrestart/perl_scandeps_cache"; # 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/)), # ignore memfd mappings qr(^/memfd:), # 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 (issues #142 #185 #267) qr#/jna\d+\.tmp( \(deleted\))?$#, qr#/.cache/JNA/#, # temporary stuff qr#^(/var)?/tmp/#, qr#^(/var)?/run/#, ]; # Verify mapped files in filesystem: # 0 : enabled # -1: ignore non-existing files, workaround for chroots and broken grsecurity kernels (default) # 1 : disable check completely, rely on content of maps file only $nrconf{skip_mapfiles} = -1; # 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; # Filter kernel image filenames by regex. This is required on Raspian having # multiple kernel image variants installed in parallel. #$nrconf{kernelfilter} = qr(kernel7\.img); # Glob used to find Linux or kFreeBSD kernel image files. #$nrconf{kernel_kfreebsd_glob} = '/boot/kfreebsd-*'; #$nrconf{kernel_linux_glob} = '/boot/vmlinu* /boot/*.img /boot/kernel*'; # Enable/disable CPU microcode update hints: # 1: requires the user to acknowledge pending updates # 0: disable microcode checks completely #$nrconf{ucodehints} = 0; # 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{verbosity} > 1); eval do { local(@ARGV, $/) = $fn; <>}; die "Error parsing $fn: $@" if($@); } } needrestart-3.11/ex/notify.conf000066400000000000000000000010411477700625400165610ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # 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.11/ex/notify.d/000077500000000000000000000000001477700625400161405ustar00rootroot00000000000000needrestart-3.11/ex/notify.d/200-write000077500000000000000000000020731477700625400175210ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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.11/ex/notify.d/400-notify-send000077500000000000000000000034211477700625400206260ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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*) DBUS_SESSION_BUS_ADDRESS=$(sed -z -n s/^DBUS_SESSION_BUS_ADDRESS=//p "/proc/$NR_SESSPPID/environ") if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then unset DBUS_SESSION_BUS_ADDRESS fi DISPLAY=$(sed -z -n s/^DISPLAY=//p "/proc/$NR_SESSPPID/environ") export DISPLAY XAUTHORITY=$(sed -z -n s/^XAUTHORITY=//p "/proc/$NR_SESSPPID/environ") export XAUTHORITY 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 -a needrestart -u critical -i dialog-warning \"$MSGTITLE\" \"$MSGBODY\"" "$NR_USERNAME" ;; *) echo "[$0] skip session '$NR_SESSION'" 1>&2 exit 1; ;; esac needrestart-3.11/ex/notify.d/600-mail000077500000000000000000000025131477700625400173140ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 ] && [ "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.11/ex/notify.d/README.needrestart000066400000000000000000000014201477700625400213340ustar00rootroot00000000000000Files 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.11/ex/polkit/000077500000000000000000000000001477700625400157105ustar00rootroot00000000000000needrestart-3.11/ex/polkit/net.fiasko-nw.needrestart.policy000066400000000000000000000013421477700625400241330ustar00rootroot00000000000000 Authentication is required to run needrestart as root view-refresh auth_admin auth_admin auth_admin /usr/sbin/needrestart true needrestart-3.11/ex/restart.d/000077500000000000000000000000001477700625400163145ustar00rootroot00000000000000needrestart-3.11/ex/restart.d/README.needrestart000066400000000000000000000010161477700625400215110ustar00rootroot00000000000000Files 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.11/ex/restart.d/dbus-broker.service000077700000000000000000000000001477700625400244272dbus.serviceustar00rootroot00000000000000needrestart-3.11/ex/restart.d/dbus.service000077500000000000000000000121041477700625400206340ustar00rootroot00000000000000#!/bin/sh # by Vladimir Kudrya # https://github.com/Vladimir-csp/ # # This script 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. See . # This is a replacement for original dbus.service script by Thomas Liske # Dbus dependencies are enumerated dynamically and restarted after dbus and systemd daemon reexec # delay in semi-interactive mode DELAY_SECONDS=10 # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi # choose interactivity mode if [ "${DEBIAN_FRONTEND:-other}" = "noninteractive" ]; then CONSOLE_MODE=skip elif [ -t 0 ]; then CONSOLE_MODE=interactive else CONSOLE_MODE=delay fi if [ "$(id -ru)" != "0" ]; then echo "Not root, exiting" >&2 exit 1 fi # get init system process name INIT_EXEC="$(ps -p 1 -o comm=)" case "$INIT_EXEC" in systemd | */systemd) true ;; *) echo "Init system is not systemd ($INIT_EXEC), doing nothing" exit 0 ;; esac # start from the name of the hook, get real unit ID (for example, dbus-broker replaces dbus) DBUS_SERVICE_NAME=$( systemctl show --value -p Id "${0##*/}" ) # if DM is active, return canonical ID DISPLAY_MANAGER=$( systemctl -q is-active display-manager.service \ && systemctl show --value -p Id display-manager.service ) # get active dependencies ACTIVE_DEPS='' while read -r service; do case "$service" in "$DISPLAY_MANAGER" | dbus.service | "$DBUS_SERVICE_NAME") continue ;; *.service) case " $ACTIVE_DEPS " in *" $service "*) true ;; *) ACTIVE_DEPS="${ACTIVE_DEPS}${ACTIVE_DEPS:+ }${service}" ;; esac ;; esac done <<- EOF $( systemctl list-dependencies -l --reverse --plain --all \ --type=service \ --state=active,reloading,failed,activating \ dbus.socket dbus.service "$DBUS_SERVICE_NAME" ) EOF # get active services with BusName current_busname='' current_id='' while IFS='=' read -r option value; do case "${option}" in BusName) current_busname="$value" continue ;; Id) current_id="$value" continue ;; '') if [ -z "$current_busname" ] || [ -z "$current_id" ]; then current_busname='' current_id='' continue fi service=$current_id current_busname='' current_id='' case "$service" in "$DISPLAY_MANAGER" | dbus.service | "$DBUS_SERVICE_NAME") continue ;; esac case " $ACTIVE_DEPS " in *" $service "*) true ;; *) ACTIVE_DEPS="${ACTIVE_DEPS}${ACTIVE_DEPS:+ }${service}" ;; esac ;; *) current_busname='' current_id='' ;; esac done <<- EOF $( systemctl show --plain --all \ --type=service \ --state=active,reloading,failed,activating \ --property=BusName,Id ) =end EOF # get logind users USERS='' while read -r _uid user _linger _state; do USERS="${USERS}${USERS:+ }${user}" done <<- EOF $(loginctl list-users --no-legend) EOF # get current dbus service PIDs DBUS_PIDS='' while read -r pid unit; do case "$unit" in "${DBUS_SERVICE_NAME}") DBUS_PIDS="${DBUS_PIDS}${DBUS_PIDS:+ }${pid}" ;; esac done <<- EOF $(ps -eo pid,unit) EOF # assemble commands COMMANDS='' # terminate users [ -n "$USERS" ] && COMMANDS="${COMMANDS}${COMMANDS:+ ; }loginctl terminate-user $USERS" # stop display manager [ -n "$DISPLAY_MANAGER" ] && COMMANDS="${COMMANDS}${COMMANDS:+ ; }systemctl stop $DISPLAY_MANAGER" # restart dbus COMMANDS="${COMMANDS}${COMMANDS:+ ; }sleep 1 ; systemctl restart $DBUS_SERVICE_NAME" # kill previous dbus pids [ -n "$DBUS_PIDS" ] && COMMANDS="${COMMANDS}${COMMANDS:+ ; }sleep 1 ; kill $DBUS_PIDS 2>/dev/null" # restart active dependencies COMMANDS="${COMMANDS}${COMMANDS:+ ; }sleep 1 ; systemctl restart $ACTIVE_DEPS" # start display manager [ -n "$DISPLAY_MANAGER" ] && COMMANDS="${COMMANDS}${COMMANDS:+ ; }systemctl start $DISPLAY_MANAGER" # normalize to single line COMMANDS=$(echo "$COMMANDS" | tr '\n' ' ' | tr -s ' ') shcat() { while IFS='' read -r line; do printf '%s\n' "$line" done } # shellcheck disable=SC2086 case "$CONSOLE_MODE" in interactive) shcat ;; delay) shcat >&2 ;; *) shcat > /dev/null ;; esac <<- EOF !!! $DBUS_SERVICE_NAME restart will be performed !!! Users to be terminated: $(printf ' %s\n' $USERS) Services to be restarted: $(printf ' %s\n' $ACTIVE_DEPS) Display manager to be restarted: ${DISPLAY_MANAGER:-no active DM found} Command set to run as transient unit restart-dbus.service: $( IFS=';' # consequent commands have a space after preceding semicolons, compensate for that printf '%s' ' ' printf ' %s\n' $COMMANDS ) Logs can be viewed by: journalctl -u restart-dbus EOF # if interactive, ask for continuation case "$CONSOLE_MODE" in interactive) printf '\n%s' "Press Enter to continue > " read -r _PRESSENTER ;; delay) printf '\n%s\n' "Restart in $DELAY_SECONDS seconds..." >&2 sleep $DELAY_SECONDS echo "Restarting..." >&2 ;; esac # run restart sequence as transient unit... # it is possible to view its output in the log if any: # journalctl -u restart-dbus systemd-run -G --unit=restart-dbus --description="Transient dbus restarter" sh -c "$COMMANDS" needrestart-3.11/ex/restart.d/systemd-manager000077500000000000000000000003571477700625400213470ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Restarting systemd using special systemctl call. # # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi exec systemctl daemon-reexec needrestart-3.11/ex/restart.d/systemd-user000077500000000000000000000017671477700625400207210ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Restarting `systemd --user` by signaling it with SIGRTMIN+25. # (documented in systemd(1) as equivalent to `systemctl --user daemon-reexec`, # but easier to do outside of a user session) # # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi # also possible to use `--value` (systemd 230+) systemctl show --state=active --property=MainPID 'user@*.service' | while IFS='=' read -r _ pid; do # skip empty lines produced by `systemctl show` if the property # did not exist or could not be queried if [ -z "$pid" ]; then continue; fi # use `env` to suppress the `kill` builtin, which might not know about # RT signals (or about _enough_ RT signals, e.g., dash) # also possible as: `systemctl kill --kill-whom=main --signal='SIGRTMIN+25' "$unit"` (systemd 252+) # also possible as: `systemctl -M "$uid@.host" --user daemon-reexec` (systemd 248+) env kill -SIGRTMIN+25 "$pid" done needrestart-3.11/ex/restart.d/sysv-init000077500000000000000000000003051477700625400202050ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Restart SysV's init. # # enable xtrace if we should be verbose if [ "$NR_VERBOSE" = '1' ]; then set -x fi exec telinit u needrestart-3.11/hooks/000077500000000000000000000000001477700625400151155ustar00rootroot00000000000000needrestart-3.11/hooks/10-dpkg000077500000000000000000000041471477700625400162140ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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>) { chomp; print "RC|$1\n" if(m@^/etc/init.d/(.+)$@ && -x $_); } close($plist); } exit(1); needrestart-3.11/hooks/20-rpm000077500000000000000000000036231477700625400160640ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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>) { chomp; print "RC|$2\n" if(m@^\S+\s+/etc(/rc\.d)?/init\.d/(.+)$@ && -x $_); } close($plist); } exit(1); needrestart-3.11/hooks/30-pacman000077500000000000000000000035221477700625400165240ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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>) { chomp; print "RC|$2\n" if(m@/etc(/rc\.d)?/init\.d/(.+)$@ && -x $_); } close($plist); } exit(1); needrestart-3.11/hooks/90-none000077500000000000000000000030551477700625400162330ustar00rootroot00000000000000#!/usr/bin/perl # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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.11/lib/000077500000000000000000000000001477700625400145405ustar00rootroot00000000000000needrestart-3.11/lib/iucode-scan-versions000077500000000000000000000046261477700625400205360ustar00rootroot00000000000000#!/bin/sh # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 # filter for processor signature (and flags if available) sig=$(iucode_tool --scan-system 2>&1 | grep -oE '[^[:space:]]+$') #' if [ -r /sys/devices/system/cpu/cpu0/microcode/processor_flags ]; then filter="-s $sig,"$(cat /sys/devices/system/cpu/cpu0/microcode/processor_flags) else filter="-S" fi # allow local command override test -r /etc/needrestart/iucode.sh && . /etc/needrestart/iucode.sh # 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 -l $filter -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 [ -n "$(find /usr/share/misc -maxdepth 1 -type f -name 'intel-microcode*' -perm /u+r)" ]; then exec iucode_tool -l $filter --ignore-broken -tb /lib/firmware/intel-ucode -ta /usr/share/misc/intel-microcode* 2>&1 exit $? fi iucode_tool -l $filter --ignore-broken $IUCODE_TOOL_EXTRA_OPTIONS -tb /lib/firmware/intel-ucode 2>&1 | grep "$sig" needrestart-3.11/lib/notify.d.sh000066400000000000000000000016251477700625400166320ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 LANG=$(sed -z -n s/^LANG=//p "/proc/$NR_SESSPPID/environ") export LANG needrestart-3.11/lib/vmlinuz-get-version000077500000000000000000000040461477700625400204360ustar00rootroot00000000000000#!/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, # prefer the final version string (linux 6.1+) grep -aoEm 1 'Linux version [[:digit:]].*#[^[:space:]]' "$1" && exit 0 grep -aoEm 1 'Linux version [[:digit:]].*#' "$1" && 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 ] || [ $# -gt 2 ] || [ ! -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.11/man/000077500000000000000000000000001477700625400145455ustar00rootroot00000000000000needrestart-3.11/man/needrestart.1000066400000000000000000000072671477700625400171630ustar00rootroot00000000000000.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|o)] [\-x] [\-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: don't restart anything and produce machine-readable output. .TP \fB\-p\fR nagios plugin mode: makes output and exit codes nagios compatible .TP \fB\-o\fR OpenMetrics output mode: output information that can be scraped by OpenMetrics-compatible services. Implies batch mode. By combining with any of `-l`, `-k` and `-w` you can decide whether the metrics will expose outdated libraries, kernel and microcode, respectively. Note that in order to list system-wide outdated libraries, needrestart needs to be run as root. When listing outdated libraries, a gauge-type metric exposes the number of running processes with such outdated libraries. When exposing kernel or microcode metrics, each one will expose a StateSet-type metric which indicates the current status. Kernel and microcode will also each expose an additional Info-type metric which informs of the versions of the current vs expected kernel or microcode. .TP \fB\-f\fR override debconf(7) frontend, sets the DEBIAN_FRONTEND environment variable to .TP \fB\-t\fR When checking running interpreter processes, allow process start times that are close to timestamps of files the interpreter uses, within this tolerance (default 2). The default value of 2 seconds is best for checks of Linux hosts, on which system limitations prevent more accurate measurements of process start times. Values higher than 0 should prevent false positives yet may in extreme cases cause false negatives; values higher than 2 should not be necessary. .TP \fB\-u\fR use preferred UI package (-u ? shows available packages) .TP \fB\-x\fR automatically exit the GUI when there is no process selected by default .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_FRONTEND\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 - 2022 (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.11/needrestart000077500000000000000000001300261477700625400162420ustar00rootroot00000000000000#!/usr/bin/perl # nagios: -epn # needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 q(/run/systemd/system); my $is_runit = -e q(/run/runit.stopit); my $is_tty = (-t *STDERR || -t *STDOUT || -t *STDIN); my $is_vm; my $is_container; if($is_systemd && -x q(/usr/bin/systemd-detect-virt)) { # check if we are inside of a vm my $ret = system(qw(/usr/bin/systemd-detect-virt --vm --quiet)); unless($? == -1 || $? & 127) { $is_vm = ($? >> 8) == 0; } # check if we are inside of a container $ret = system(qw(/usr/bin/systemd-detect-virt --container --quiet)); unless($? == -1 || $? & 127) { $is_container = ($? >> 8) == 0; } } elsif(eval "use ImVirt; 1;") { require ImVirt; ImVirt->import(); my $imvirt = ImVirt::imv_get(ImVirt->IMV_PROB_DEFAULT); $is_vm = $imvirt ne ImVirt->IMV_PHYSICAL; $is_container = $imvirt eq ImVirt->IMV_CONTAINER; } elsif (-r "/proc/1/environ") { # check if we are inside of a container (fallback) local $/; open(HENV, '<', '/proc/1/environ'); $is_container = scalar(grep {/^container=/;} unpack("(Z*)*", )); close(HENV) } sub HELP_MESSAGE { print <] [-r ] [-f ] [-u ] [-(b|p|o)] [-x] [-klw] -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 -o enable OpenMetrics output mode, implies batch mode, cannot be used simultaneously with -p -f override debconf frontend (DEBIAN_FRONTEND, debconf(7)) -t tolerate interpreter process start times within this value -u use preferred UI package (-u ? shows available packages) -x do not ask for restarts if no process is selected by default 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 - 2022 (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_cont => [], blacklist_interp => [], blacklist_rc => [], blacklist_mappings => [], override_rc => {}, override_cont => {}, skip_mapfiles => -1, interpscan => 1, perlcache => undef, kernelhints => 1, kernelfilter => qr(.), ucodehints => 1, q(nagios-status) => { services => 1, kernel => 2, ucode => 2, sessions => 2, containers => 1, }, has_pam_systemd => 1, tolerance => 2, exitWhenNoneSelected => 0, kernel_kfreebsd_glob => '/boot/kfreebsd-*', kernel_linux_glob => '/boot/vmlinu* /boot/*.img /boot/kernel*', ); # 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_o; our $opt_q; our $opt_t; our $opt_u; our $opt_w; our $opt_x; unless(getopts('c:vr:nm:bf:klpoqt:u:wx')) { 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); # override debconf frontend $ENV{DEBIAN_FRONTEND} = $opt_f if($opt_f); my $debian_noninteractive = (exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive'); # 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 $/; open my $fh, $opt_c or die "ERROR: $!\n"; my $cfg = <$fh>; close($fh); $cfg; }; 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' && $debian_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'); $opt_t = $nrconf{tolerance} unless(defined($opt_t)); $nrconf{defno}++ if($opt_n); die "Options -p and -o cannot be defined simultaneously\n" if ($opt_p && $opt_o); $opt_b++ if($opt_p || $opt_o); $nrconf{exitWhenNoneSelected}++ if($opt_x); needrestart_interp_configure({ perl => { cache_file => $nrconf{perlcache}, }, }); # 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); # we need to run as root in order to list system-wide outdated libraries if ($opt_o && $opt_l) { print STDERR "$LOGPREF OpenMetrics output needs root access to list processes with outdated libraries\n"; exit 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)); # Disable UI interactiveness $ui->interactive(0) if ($ui->can("interactive") && $debian_noninteractive); # 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 : $nrconf{ucodehints}); } 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 vm detected\n" if($nrconf{verbosity} > 1 && $is_vm); 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)); } } elsif($is_runit && -d qq(/etc/sv/$rc)) { if(-e qq(/etc/service/$rc)) { (qw(sv restart), $rc); } else { (q(service), $rc, q(restart)); } } 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 && !$opt_o); my %ometric_kernel_values = ( kresult => q(unknown), krunning => q(unknown), kexpected => q(unknown), ); my %ometric_ucode_values = ( status => q(unknown), current => q(unknown), expected => q(unknown), ); my %restart; my %sessions; my @guests; 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}}); # Sync $exe with the initial value from Proc::ProcessTable to prevent race # conditions in later checks. if(defined($ptable->{$pid}->{exec})) { $exe = $ptable->{$pid}->{exec}; } # Proc::ProcessTable's exec field is undef if the file is not accessible in # the root mountns, so the value of $exe is used instead. else { $ptable->{$pid}->{exec} = $exe; } # 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 is $exe\n" if($nrconf{verbosity} > 1); print STDERR "$LOGPREF #$pid uses deleted $path\n" if($nrconf{verbosity} > 1); $restart++; last; } # check for outdated lib mappings unless($nrconf{skip_mapfiles} == 1) { $maddr =~ s/^0+([^-])/$1/; $maddr =~ s/-0+(.)/-$1/; my @paths = ("/proc/$pid/map_files/$maddr", "/proc/$pid/root/$path"); my ($testp) = grep { -e $_; } @paths; unless($testp) { unless($nrconf{skip_mapfiles} == -1) { print STDERR "$LOGPREF #$pid is $exe\n" if($nrconf{verbosity} > 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); unless($sdev) { print STDERR "$LOGPREF #$pid map stat for $testp failed: $!\n" if($nrconf{skip_mapfiles} == 0 && $nrconf{verbosity} > 1); next; } my @sdevs = ( # glibc gnu_dev_* definition from sysmacros.h sprintf("%x:%x", (($sdev >> 8) & 0xfff) | (($sdev >> 32) & ~0xfff), ($sdev & 0xff) | (($sdev >> 12) & ~0xff)), # Traditional definition of major(3) and minor(3) sprintf("%x:%x", $sdev >> 8, $sdev & 0xff), # kFreeBSD: /proc//maps does not contain device IDs qq(0:0) ); # 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); if ($major == 0 || $major == 144 || $major == 145 || $major == 146) { $mdev = "0:0"; } else { # strip leading zeros $mdev =~ s/(^|:)0+([\da-f]+)/$1$2/g; } # 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 =~ /^0:/)) { print STDERR "$LOGPREF #$pid is $exe\n" if($nrconf{verbosity} > 1); 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}, $opt_t)); } # 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 && !($is_systemd && nr_is_systemd_manager($ppid))) { 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...'); PIDLOOP: 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) { # get unit name from /proc//cgroup my $cgroup = nr_get_cgroup($pid); next unless(defined($cgroup)); # systemd manager if($cgroup =~ m@^/init\.scope$@ || ($pid == 1 && $exe =~ m@^(/usr)?/lib/systemd/systemd@)) { print STDERR "$LOGPREF #$pid is systemd manager\n" if($nrconf{verbosity} > 1); $restart{q(systemd-manager)}++; next; } # `systemd --user` manager if($cgroup =~ m@/user\@(\d+)\.service/init\.scope$@ && $ptable->{$pid}->{fname} ne "(sd-pam)") { print STDERR "$LOGPREF #$pid is user systemd manager: uid=$1\n" if($nrconf{verbosity} > 1); # TODO: restart specific `systemd --user` instance? $restart{q(systemd-user)}++; next; } if($cgroup =~ 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($cgroup =~ m@/user\@(\d+)\.service(/.+\.slice)*/([^/]+\.service)$@) { print STDERR "$LOGPREF #$pid part of user service: uid=$1 unit=$3\n" if($nrconf{verbosity} > 1); push(@{ $sessions{$1}->{'user service'}->{ $3 } }, $pid); next; } if($cgroup =~ m@/user\@(\d+)\.service@) { print STDERR "$LOGPREF #$pid part of user manager: uid=$1\n" if($nrconf{verbosity} > 1); push(@{ $sessions{$1}->{'user manager'}->{ $ptable->{$pid}->{fname} } }, $pid); next; } if($cgroup =~ m@/machine.slice/machine.qemu(.*).scope@) { for my $cmdlineidx (0 .. $#{$ptable->{$pid}->{cmdline}} ) { if ( ${$ptable->{$pid}->{cmdline}}[$cmdlineidx] eq "-name") { foreach ( split(/,/, ${$ptable->{$pid}->{cmdline}}[$cmdlineidx+1]) ) { if ( index($_, "guest=") == 0 ) { my @namearg = split(/=/, $_, 2); if ($#{namearg} == 1) { print STDERR "$LOGPREF #$pid detected as VM guest '$namearg[1]' in group '$cgroup'\n" if($nrconf{verbosity} > 1); push(@guests, __x("'{name}' with pid {pid}", name => $namearg[1], pid=>$pid) ); } next PIDLOOP; } } } } print STDERR "$LOGPREF #$pid detected as VM guest with unknown name in group '$cgroup'\n" if($nrconf{verbosity} > 1); push(@guests, __x("'Unknown VM' with pid {pid}", pid=>$pid) ); next; } elsif($cgroup =~ m@/([^/]+\.service)$@) { my $unit = $1; print STDERR "$LOGPREF #$pid is $unit\n" if($nrconf{verbosity} > 1); $restart{$unit}++; next; } elsif($cgroup) { print STDERR "$LOGPREF #$pid unexpected cgroup '$cgroup'\n" if($nrconf{verbosity} > 1); } # 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 (normally). # 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 children (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. print STDERR "$LOGPREF #$pid running $hook no perfect hit found $found pids $#nopids\n" if($nrconf{verbosity} > 1); 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 superseded 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 stuff within container if($is_container || needrestart_cont_check($nrconf{verbosity} > 1, 1, nr_readlink(1), 1)) { print STDERR "$LOGPREF inside container, skipping kernel checks\n" if($nrconf{verbosity} > 1); $opt_k = undef; } # Skip uCode stuff within container or vm if($is_container || $is_vm || needrestart_cont_check($nrconf{verbosity} > 1, 1, nr_readlink(1), 1)) { print STDERR "$LOGPREF inside container or vm, skipping microcode checks\n" if($nrconf{verbosity} > 1); $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, $nrconf{kernelfilter}, $ui, \%nrconf) : ()); if(defined($kresult)) { if($opt_b) { unless($opt_p || $opt_o) { print "NEEDRESTART-KCUR: $kvars{KVERSION}\n"; print "NEEDRESTART-KEXP: $kvars{EVERSION}\n" if(defined($kvars{EVERSION})); print "NEEDRESTART-KSTA: $kresult\n"; } elsif ($opt_p) { $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} .= " (!!)"; } } elsif ($opt_o) { my %kernel_states = ( &NRK_NOUPGRADE => "current", &NRK_ABIUPGRADE => "abi_upgrade", &NRK_VERUPGRADE => "version_upgrade", ); $ometric_kernel_values{kresult} = $kernel_states{$kresult}; $ometric_kernel_values{krunning} = $kvars{KVERSION}; $ometric_kernel_values{kexpected} = $kvars{EVERSION}; } } 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($opt_w) { if($opt_b) { unless($opt_p || $opt_o) { print "NEEDRESTART-UCSTA: $ucode_result\n"; if($ucode_result != NRM_UNKNOWN) { print "NEEDRESTART-UCCUR: $ucode_vars{CURRENT}\n" if (defined($ucode_vars{CURRENT})); print "NEEDRESTART-UCEXP: $ucode_vars{AVAIL}\n" if (defined($ucode_vars{AVAIL})); } } else { if ($opt_p) { 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} .= " (!!)"; } } elsif ($opt_o) { my %ucode_states = ( &NRM_CURRENT => "current", &NRM_OBSOLETE => "obsolete", &NRM_UNKNOWN => "unknown", ); $ometric_ucode_values{status} = $ucode_states{$ucode_result}; $ometric_ucode_values{current} = defined($ucode_vars{CURRENT}) ? $ucode_vars{CURRENT} : "unknown"; $ometric_ucode_values{expected} = defined($ucode_vars{AVAIL}) ? $ucode_vars{AVAIL} : "unknown"; } } } 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} < 0) { $ui->vspace(); $ui->notice(__x( 'The currently running processor microcode revision is {crev} which is not the expected microcode revision {erev}.', crev => $ucode_vars{CURRENT}, erev => $ucode_vars{AVAIL}, )); } elsif($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} .= " (!!)"; } } my @sorted_override_rc_keys = sort keys %{$nrconf{override_rc}}; 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 || $opt_o); 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 (@sorted_override_rc_keys) { 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); }, $nrconf{exitWhenNoneSelected}); 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); for my $re (@{$nrconf{blacklist_cont}}) { delete $conts{$_} for grep /$re/, keys %conts; } 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 || $opt_o); 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)); } } } } } } ## GUESTS $ui->vspace(); if (! @guests) { $ui->notice(__ 'No VM guests are running outdated hypervisor (qemu) binaries on this host.') unless($opt_b || $opt_m eq 'e'); } else { if($opt_m eq 'e') { push(@easy_hints, __ 'outdated VM guests'); } else { unless($opt_p || $opt_b) { $ui->notice(__ 'VM guests are running outdated hypervisor (qemu) binaries on this host:'); foreach ( @guests ) { $ui->notice(" $_"); } } } } } # 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); } my @sessions_list; if(scalar %sessions) { # build a sorted list of user @ session strings # # used in the nagios and batch outputs below @sessions_list = 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 } # 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 && $nagios{kret} != 3) ? "Kernel=$nagios{kperf};0;;0;2" : ()), ( ($opt_w && $nagios{mret} != 3) ? "Microcode=$nagios{mperf};0;;0;1" : ()), ( ($opt_l && $nagios{sret} != 3) ? "Services=$nagios{sperf};;0;0" : ()), ( ($opt_l && $nagios{cret} != 3) ? "Containers=$nagios{cperf};;0;0" : ()), ( ($opt_l && $nagios{uret} != 3) ? "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- ", '', @sessions_list), "\n"; } exit $ret; } if ($opt_o) { print "# TYPE needrestart_build_info gauge\n"; print "# HELP needrestart_build_info information about needrestart's runtime build\n"; print "needrestart_build_info{version=\"$NeedRestart::VERSION\",perl_version=\"$^V\"} 1\n"; if ($opt_k) { print "# TYPE needrestart_kernel_status gauge\n"; print "# HELP needrestart_kernel_status status of kernel as reported by needrestart\n"; print "needrestart_kernel_status{needrestart_kernel_status=\"$ometric_kernel_values{kresult}\"} 1\n"; print "# TYPE needrestart_kernel_info gauge\n"; print "# HELP needrestart_kernel_info version information for currently running and most up to date kernels\n"; print "needrestart_kernel{running=\"$ometric_kernel_values{krunning}\",expected=\"$ometric_kernel_values{kexpected}\"} 1\n"; } if ($opt_w) { print "# TYPE needrestart_ucode_status gauge\n"; print "# HELP needrestart_ucode_status status of the host's CPU microcode as reported by needrestart\n"; print "needrestart_ucode_status{needrestart_ucode_status=\"$ometric_ucode_values{status}\"} 1\n"; print "# TYPE needrestart_ucode_info gauge\n"; print "# HELP needrestart_ucode_info version information for currently used and available microcode\n"; print "needrestart_ucode{running=\"$ometric_ucode_values{current}\",expected=\"$ometric_ucode_values{expected}\"} 1\n"; } if ($opt_l) { my $ometric_num_services = scalar %restart; print "# TYPE needrestart_processes_with_outdated_libraries gauge\n"; print "# HELP needrestart_processes_with_outdated_libraries number of processes requiring a restart\n"; print "needrestart_processes_with_outdated_libraries $ometric_num_services\n"; } print "# EOF\n"; exit 0; } if ($opt_b and scalar %sessions) { for my $sess (@sessions_list) { print "NEEDRESTART-SESS: $sess\n"; } } needrestart-3.11/perl/000077500000000000000000000000001477700625400147345ustar00rootroot00000000000000needrestart-3.11/perl/Makefile.PL000066400000000000000000000004221477700625400167040ustar00rootroot00000000000000use ExtUtils::MakeMaker; WriteMakefile( 'AUTHOR' => 'Thomas Liske ', 'LICENSE' => 'gpl', 'NAME' => 'NeedRestart', 'PREREQ_PM' => { Module::Find => 0, Proc::ProcessTable => 0, Sort::Naturally => 0, Term::ReadKey => 0. }, ); needrestart-3.11/perl/lib/000077500000000000000000000000001477700625400155025ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart.pm000066400000000000000000000145421477700625400202660ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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_configure 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 needrestart_cont_register_fallback ); 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 needrestart_cont_register_fallback )], ); our $VERSION = '3.11'; 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 $InterpConf; my %InterpCache; my $idebug; sub needrestart_interp_configure($) { my $conf = shift; $InterpConf = $conf; } sub needrestart_interp_register($$) { my $pkg = shift; my $confkey = shift; $Interps{$pkg} = new $pkg($idebug, $InterpConf->{$confkey}); } 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; my $tolerance = 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 + $tolerance} 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 %FALLBACK; my $ndebug; sub needrestart_cont_register($) { my $pkg = shift; $CONT{$pkg} = new $pkg($ndebug); } sub needrestart_cont_register_fallback($) { my $pkg = shift; $FALLBACK{$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)); } foreach my $cont (values %FALLBACK) { 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.11/perl/lib/NeedRestart/000077500000000000000000000000001477700625400177225ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart/CONT.pm000066400000000000000000000034661477700625400210340ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 $root_pidns = nr_get_pid_ns(1); my $ptable = nr_ptable(); sub new { my $class = shift; my $debug = shift; die "Could not get PID namespace of #1!\n" unless(defined($root_pidns)); return bless { debug => $debug, pidns => $root_pidns, }, $class; } sub check { my $self = shift; return 0; } sub get { my $self = shift; return (); } sub in_pidns { my $self = shift; my $pid = shift; my $ns = nr_get_pid_ns($pid); return $ns && $ns != $self->{pidns}; } sub find_nsparent { my $self = shift; my $pid = shift; return undef unless(exists($ptable->{$pid})); my $ns = nr_get_pid_ns($ptable->{$pid}->{ppid}); return $ptable->{$pid}->{ppid} if($ns && $ns == $self->{pidns}); return $self->find_nsparent($ptable->{$pid}->{ppid}); } 1; needrestart-3.11/perl/lib/NeedRestart/CONT/000077500000000000000000000000001477700625400204655ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart/CONT/LXC.pm000066400000000000000000000060421477700625400214530ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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(@_); $self->{lxc} = {}; $self->{lxd} = {}; if (-d q(/snap/lxd)) { $self->{has_lxd} = 1; $self->{lxd_bin} = q(/snap/bin/lxc); $self->{lxd_container_path} = q(/var/snap/lxd/common/lxd/containers); print STDERR "$LOGPREF LXD installed via snap\n" if($self->{debug}); } elsif (-x q(/usr/bin/incus)) { $self->{has_lxd} = 1; $self->{lxd_bin} = q(/usr/bin/incus); $self->{lxd_container_path} = q(/var/lib/incus/containers); } else { $self->{has_lxd} = -x q(/usr/bin/lxc); $self->{lxd_bin} = q(/usr/bin/lxc); $self->{lxd_container_path} = q(/var/lib/lxd/containers); } return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; # stop here if no dedicated PID namespace is used return 0 unless $self->in_pidns($pid); my $cg = nr_get_cgroup($pid); return unless(defined($cg)); # look for LXC cgroups return unless($cg =~ m@^/lxc(?:.payload)?[./]([^/\n]+)($|/)@); my $name = $1; my $type = ($self->{has_lxd} && -d qq($self->{lxd_container_path}/$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; sub lxd_restart_with_project { my ($bin, $container) = @_; my @parts = split(/_/, $container); if ($#parts == 1) { return [ $bin, 'restart', qq(--project=$parts[0]), $parts[1] ]; } else { [ $bin, 'restart', $container ] } } return (map { ($_ => [qw(lxc-stop --reboot --name), $_]); } keys %{ $self->{lxc} }), (map { ($_ => lxd_restart_with_project($self->{lxd_bin}, $_)); } keys %{ $self->{lxd} }); } 1; needrestart-3.11/perl/lib/NeedRestart/CONT/docker.pm000066400000000000000000000036171477700625400223010ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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(@_); return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; # stop here if no dedicated PID namespace is used return 0 unless $self->in_pidns($pid); my $cg = nr_get_cgroup($pid); return 0 unless(defined($cg)); # look for docker cgroups return 0 unless($cg =~ m@^/system.slice/docker-(.+)\.scope$@ || $cg =~ m@^/system.slice/docker\.service$@ || $cg =~ m@^/docker/([\da-f]+)$@); 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.11/perl/lib/NeedRestart/CONT/machined.pm000066400000000000000000000043661477700625400226040ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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(@_); $self->{machined} = {}; return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; # stop here if no dedicated PID namespace is used return 0 unless $self->in_pidns($pid); my $cg = nr_get_cgroup($pid); return 0 unless(defined($cg)); # look for machined or systemd-nspawn cgroups return 0 unless($cg =~ m@^/machine\.slice/(machine)-([^.]+)\.scope(/|$)@m || $cg =~ m@^/machine\.slice/(systemd-nspawn)\@([^.]+)\.service(/|$)@); my $name = $2; my $mgr = ($1 eq "machine") ? "systemd-machined" : $1; unless($norestart) { print STDERR "$LOGPREF #$pid is part of $mgr container '$name' and should be restarted\n" if($self->{debug}); $self->{machined}->{$name}++; } else { print STDERR "$LOGPREF #$pid is part of $mgr container '$name'\n" if($self->{debug}); } return 1; } sub get { my $self = shift; return map { ($_ => [qw(machinectl reboot), $_]); } keys %{ $self->{machined} }; } 1; needrestart-3.11/perl/lib/NeedRestart/CONT/other.pm000066400000000000000000000031611477700625400221450ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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::other; use strict; use warnings; use parent qw(NeedRestart::CONT); use NeedRestart qw(:cont); use NeedRestart::Utils; my $LOGPREF = '[other]'; needrestart_cont_register_fallback(__PACKAGE__) unless($<); sub new { my $class = shift; my $self = $class->SUPER::new(@_); return bless $self, $class; } sub check { my $self = shift; my $pid = shift; my $bin = shift; my $norestart = shift; # stop here if no dedicated PID namespace is used return 0 unless $self->in_pidns($pid); print STDERR "$LOGPREF #$pid is part of a PID namespace and will be ignored\n" if($self->{debug}); return 1; } sub get { my $self = shift; return (); } 1; needrestart-3.11/perl/lib/NeedRestart/Interp.pm000066400000000000000000000023601477700625400215220ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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; my $conf = shift; return bless { debug => $debug, conf => $conf, }, $class; } sub isa($$) { my $self = shift; return 0; } sub source($$) { return (); } sub files($$) { return (); } 1; needrestart-3.11/perl/lib/NeedRestart/Interp/000077500000000000000000000000001477700625400211635ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart/Interp/Java.pm000066400000000000000000000032111477700625400223770ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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__, "java"); 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.11/perl/lib/NeedRestart/Interp/Perl.pm000066400000000000000000000137421477700625400224320ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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; my $LOGPREF = '[Perl]'; needrestart_interp_register(__PACKAGE__, "perl"); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@^/usr/(local/)?bin/perl(5[.\d]*)?$@); return 0; } sub _scan($$$$$) { my $debug = shift; my $pid = shift; my $src = shift; my $files = shift; my $path = shift; my $fh; open($fh, '<', "/proc/$pid/root/$src") || return; # find used modules my %modules = map { (/^\s*use\s+([a-zA-Z][\w:]+)/ ? ($1 => 1) : ()) } <$fh>; close($fh); # track file $files->{$src}++; # scan module files if(scalar keys %modules) { foreach my $module (keys %modules) { # skip some well-known Perl pragmas next if ($module =~ /^(constant|strict|vars|v5(\.\d+)?|warnings)$/); $module =~ s@::@/@g; $module .= '.pm'; 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 undef; } 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()) { chdir($cwd); print STDERR "$LOGPREF #$pid: process cwd is unreachable\n" if($self->{debug}); return undef; } # 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(defined($src) && -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()) { chdir($cwd); 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(defined($src) && -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 @path; local %ENV; # get include path from env my %e = nr_parse_env($pid); if(exists($e{PERL5LIB})) { @path = split(':', $e{PERL5LIB}); } # get include path from @INC my $plread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'print(join("\n", @INC));'); push(@path, <$plread>); close($plread); 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.11/perl/lib/NeedRestart/Interp/Python.pm000066400000000000000000000146711477700625400230130ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 File::Temp qw(tempdir); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Python]'; my $empty_dir; needrestart_interp_register(__PACKAGE__, "python"); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@^/usr/(local/)?bin/python([23][.\d]*)?$@); return 0; } sub _scan($$$$$) { my $debug = shift; my $pid = shift; my $src = shift; my $files = shift; my $path = shift; my $fh; open($fh, '<', "/proc/$pid/root/$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); } } } } # chdir into empty directory to prevent python parsing arbitrary files sub chdir_empty() { unless(defined($empty_dir)) { $empty_dir = tempdir(CLEANUP => 1); } chdir($empty_dir); } 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 undef; } 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()) { chdir($cwd); print STDERR "$LOGPREF #$pid: process cwd is unreachable\n" if($self->{debug}); return undef; } # 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(defined($src) && -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()) { chdir($cwd); 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(defined($src) && -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 @path; local %ENV; # get include path from env my %e = nr_parse_env($pid); if(exists($e{PYTHONPATH})) { @path = split(':', $e{PYTHONPATH}); } # get include path from sys.path chdir_empty(); 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); chdir("/proc/$pid/root/$ptable->{cwd}"); # look for module source files if(defined($path)) { chomp($path); $path =~ s/^\['//; $path =~ s/'\$//; push(@path, 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.11/perl/lib/NeedRestart/Interp/Ruby.pm000066400000000000000000000141171477700625400224460ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 File::Temp qw(tempdir); use Getopt::Std; use NeedRestart qw(:interp); use NeedRestart::Utils; my $LOGPREF = '[Ruby]'; my $empty_dir; needrestart_interp_register(__PACKAGE__, "ruby"); sub isa { my $self = shift; my $pid = shift; my $bin = shift; return 1 if($bin =~ m@^/usr/(local/)?bin/ruby(\d[.\d]*)?$@); return 0; } sub _scan($$$$$) { my $debug = shift; my $pid = shift; my $src = shift; my $files = shift; my $path = shift; my $fh; open($fh, '<', "/proc/$pid/root/$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); } } } } # chdir into empty directory to prevent ruby parsing arbitrary files sub chdir_empty() { unless(defined($empty_dir)) { $empty_dir = tempdir(CLEANUP => 1); } chdir($empty_dir); } 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 undef; } 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()) { chdir($cwd); print STDERR "$LOGPREF #$pid: process cwd is unreachable\n" if($self->{debug}); return undef; } # 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(defined($src) && -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()) { chdir($cwd); 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 = abs_path($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})) { 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 @path; local %ENV; # get include path from env my %e = nr_parse_env($pid); if(exists($e{RUBYLIB})) { @path = split(':', $e{RUBYLIB}); } # get include path chdir_empty(); my $rbread = nr_fork_pipe($self->{debug}, $ptable->{exec}, '-e', 'puts $:'); push(@path, <$rbread>); close($rbread); chomp(@path); chdir("/proc/$pid/root/$ptable->{cwd}"); 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.11/perl/lib/NeedRestart/Kernel.pm000066400000000000000000000104251477700625400215020ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 $filter = shift; my $ui = shift; my $nrconf = 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, \$filter, \$ui, \$nrconf);") { 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.11/perl/lib/NeedRestart/Kernel/000077500000000000000000000000001477700625400211425ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart/Kernel/Linux.pm000066400000000000000000000121141477700625400225760ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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, 512); 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 $filter = shift; my $ui = shift; my $nrconf = 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 { # whitelist kernel images m/$filter/; } grep { # filter initrd images (!m@^/boot/init@); } (glob($nrconf->{kernel_linux_glob})); $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.11/perl/lib/NeedRestart/Kernel/kFreeBSD.pm000066400000000000000000000060001477700625400230610ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 $filter = shift; my $ui = shift; my $nrconf = 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 = grep {m/$filter/;} reverse nsort glob($nrconf->{kernel_kfreebsd_glob}); $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.11/perl/lib/NeedRestart/Strings.pm000066400000000000000000000041361477700625400217150ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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.11/perl/lib/NeedRestart/UI.pm000066400000000000000000000161251477700625400206020ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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); use Term::ReadKey; # NeedRestart::UI internals properties # ==================================== # # $self->{verbosity}: 1 if needrestart is in verbose mode, 0 # otherwise. # # $self->{progress}: if undef, disable the progress bar. Otherwise: # # $self->{progress}->{msg}: message to print (last message printed). # # $self->{progress}->{count}: current progress (number of steps done # since the beginning). # # $self->{progress}->{max}: Expected total number of steps. If 0, # the bar will always be at 0. # # $self->{fhin}, $self->{fhout}: original stdin/stdout filehandles. # NeedRestart::UI may change the filehandles to ensure we have a # terminal. The original filehandles are saved in these two # attributes in progress_prep, and restored in progress_fin. # my $ui = new NeedRestart::UI(VERBOSITY); # # VERBOSITY indicates whether needrestart is otherwise verbose (0 or # 1). If VERBOSITY is 1, we disable the progress indicator: # otherwise, the output would not be nice. sub new { my $class = shift; my $verbosity = shift; return bless { verbosity => $verbosity, progress => undef, }, $class; } # my $nb_columns = _get_terminal_columns(FILEHANDLE); # e.g.: my $nb_columns = _get_terminal_columns(\*STDOUT); # => 103 # # This is a wrapper for GetTerminalSize to cope with Debian # Bug#824564. sub _get_terminal_columns { my ($filehandle) = @_; # workaround Debian Bug#824564 in Term::ReadKey: pass filehandle # twice my ($columns) = GetTerminalSize($filehandle, $filehandle); return $columns; } # my $columns = &_get_columns(); # # Return the number of columns to use for output. sub _get_columns { my $default_columns = 80; # Sane default if (-t *STDOUT) { my ($columns) = _get_terminal_columns(\*STDOUT); # Cope with 0-width terminals (see Debian bug #942759). return $columns == 0? $default_columns: $columns; } else { return $default_columns; } } # $ui->wprint(FILEHANDLE, SP1, SP2, MESSAGE); # # Print the MESSAGE to the given FILEHANDLE, wrapping text if we can get # the number of columns. # # SP1 and SP2 are resp. Text::Wrap::wrap's $initial_tab and # $subsequent_tab. 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) { my ($cols) = _get_terminal_columns($fh, $fh); $Text::Wrap::columns = $cols? $cols: 80; print $fh wrap($sp1, $sp2, $message); } else { print $fh "$sp1$message"; } } # $ui->progress_prep(MAX, OUT); # # Prepare for displaying a new progress bar. # # Disable the progress bar if we don't have a terminal. Restore the # terminal if necessary. Reset the progress counter. Print the # initial line. # # MAX: expected total number of steps. # # OUT: the message, e.g. "Scanning processes..." 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); } # $ui->progress_step(); # # Add one step to the progress and update the display. sub progress_step($) { my $self = shift; return unless defined($self->{progress}); $self->_progress_inc(); 1; } # $ui->progress_fin(); # # Restore stdin/out as they were before the preparation. 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}); } # $ui->_progress_msg(MESSAGE); # # Set the current MESSAGE and update the display. sub _progress_msg { my $self = shift; return unless defined($self->{progress}); $self->{progress}->{msg} = shift; $self->_progress_out(); } # $ui->_progress_inc(); # # Increase progress by one step and redisplay. sub _progress_inc { my $self = shift; $self->{progress}->{count}++; $self->_progress_out(); } # $ui->_progress_out(); # # Print the current message and progress bar. sub _progress_out { my $self = shift; my $msg = $self->{progress}->{msg}; my $max = $self->{progress}->{max}; my $count = $self->{progress}->{count}; # The line looks like this: # my message [==== ] # <- wmsg ->..<---- wbar -------->. # 3 columns are preassigned (the space and the square brackets); # we need to split the remaining space between the message and the # bar itself. my $remaining_space = _get_columns() - 3; # We use 70% max of the remaining space. my $wmsg = int($remaining_space * 0.7); # Shrink if the message is actually shorter. $wmsg = length($msg) if(length($msg) < $wmsg); my $wbar = $remaining_space - $wmsg; my $bar = '=' x ($wbar*( $max > 0 ? $count/$max : 0 )); printf("%-${wmsg}s [%-${wbar}s]\r", substr($msg, 0, $wmsg), $bar); } # $ui->_progress_fin(); # # Finish the progress. Redisplay the line, removing the bar. sub _progress_fin { my $self = shift; my $columns = _get_columns; $self->{progress}->{count} = 0; 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.11/perl/lib/NeedRestart/UI/000077500000000000000000000000001477700625400202375ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart/UI/Debconf.pm000066400000000000000000000150521477700625400221400ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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; my $exitWhenNoneSelected = 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); } return if $exitWhenNoneSelected && scalar(@selected) == 0; 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); } # Workaround for Debian Bug#893152 # # Using Debconf leaks a fd to this module's source file. Since Perl seems # not to set O_CLOEXEC the fd keeps open if the Debconf package uses fork # to restart needrestart piped to Debconf. The FD will leak into restarted # daemons if using Sys-V init. foreach my $fn () { my $dst = readlink($fn); # check if the FD is the package source file if ($dst && ($dst eq __FILE__) && $fn =~ /\/(\d+)$/) { open(my $fh, "<&=", $1) || warn("$!\n"); close($fh); } } 1; needrestart-3.11/perl/lib/NeedRestart/UI/stdio.pm000066400000000000000000000117641477700625400217300ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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); # The default is to be interactive my $INTERACTIVE = 1; sub interactive { my $self = shift; $INTERACTIVE = shift; } 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 && $INTERACTIVE); } 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 && $INTERACTIVE); } 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 && $INTERACTIVE); } 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.11/perl/lib/NeedRestart/Utils.pm000066400000000000000000000112461477700625400213640ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 nr_get_cgroup nr_is_systemd_manager nr_get_ns nr_get_pid_ns ); my %ptable; { local $SIG{__WARN__} = sub {}; %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_get_cgroup($) { my $pid = shift; # get unit name from /proc//cgroup if(open(HCGROUP, qq(/proc/$pid/cgroup))) { my ($cgroup) = map { chomp; my ($id, $type, $value) = split(/:/); if(($id == 0 && $type eq "") || ($type eq q(name=systemd))) { ($value); } else { (); } } ; close(HCGROUP); return $cgroup; } return undef; } sub nr_is_systemd_manager($) { my $pid = shift; my $cgroup = nr_get_cgroup($pid); return $cgroup =~ m@(^|/user\@(\d+)\.service)/init\.scope$@ if($cgroup); return 0; } sub nr_get_ns($$) { my $pid = shift; my $ns = shift; my $stat = nr_stat(qq(/proc/$pid/ns/$ns)); return $stat->{ino} if($stat); return undef; } sub nr_get_pid_ns($) { my $pid = shift; return nr_get_ns($pid, '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.11/perl/lib/NeedRestart/uCode.pm000066400000000000000000000115431477700625400213230ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 nr_ucode_register NRM_UNKNOWN NRM_CURRENT NRM_OBSOLETE ); my $LOGPREF = '[ucode]'; sub compare_ucode_versions { my ($debug, $processor, %vars) = @_; # if no firmware is available for the current CPU, that's # considered up to date. the rationale here is that if we warn on # this, we're actually going to warn for certain new CPUs that # have an up-to-date, built-in firmware without any update. that, # in turn, creates alert fatigue and makes operators more likely # to ignore warnings. unless ( exists( $vars{AVAIL} ) ) { print STDERR "$LOGPREF #$processor did not get available microcode version\n" if ( $debug ); return NRM_CURRENT; } # from here on, there is a microcode file available # # if we can't find a microcode firmware for the current CPU, # *that* is a problem. unless ( exists( $vars{CURRENT} ) ) { print STDERR "$LOGPREF #$processor did not get current microcode version\n" if ( $debug); return NRM_UNKNOWN; } if ( hex( $vars{CURRENT} ) >= hex( $vars{AVAIL} ) ) { return NRM_CURRENT; } return NRM_OBSOLETE; } sub nr_ucode_check { my $debug = shift; my $ui = shift; my @PKGS; # autoload ucode modules foreach my $module ( findsubmod NeedRestart::uCode ) { unless ( eval "use $module (); 1;" ) { warn "$LOGPREF Failed to load $module: $@" if ( $@ && $debug ); } else { print STDERR "$LOGPREF using $module\n" if ($debug); push( @PKGS, $module ); } } unless ( scalar @PKGS > 0 ) { print STDERR "$LOGPREF no supported processor microcode detection\n" if ($debug); return ( NRM_UNKNOWN, () ); } # parse /proc/cpuinfo my %processors; my %sockels; { my $fh; unless ( open( $fh, '<', '/proc/cpuinfo' ) ) { warn "$LOGPREF Failed to read /proc/cpuinfo: $!\n" if ($debug); return ( NRM_UNKNOWN, () ); } local $/ = "\n\n"; while (<$fh>) { # transform key: value into hash my %data; foreach ( split(/\n+/) ) { $data{$1} = $2 if (/^(.+\S)\s*: (.+)$/); } if ( defined( $data{processor} ) ) { # save processor details $processors{ $data{processor} } = \%data; # save physical to logical mapping my $sockel = 0; if ( defined( $data{'physical id'} ) ) { $sockel = $data{'physical id'}; } push( @{ $sockels{$sockel} }, $data{processor} ); } } } $ui->progress_prep( (scalar keys %sockels) * (scalar @PKGS), __ 'Scanning processor microcode...' ); my ( $state, @vars ) = (NRM_UNKNOWN); foreach my $sid ( keys %sockels ) { my $pid = $sockels{$sid}[0]; # call ucode modules foreach my $pkg (@PKGS) { my @nvars; eval "\@nvars = ${pkg}::nr_ucode_check_real(\$debug, \$ui, \$processors{\$pid});"; if ( $@ ) { print STDERR $@ if ($debug); $ui->progress_step; next; } $ui->progress_step; my $nstate = compare_ucode_versions( $debug, $pid, @nvars ); if ( $nstate > $state ) { ( $state, @vars ) = ( $nstate, @nvars ); } if ( $nstate == NRM_OBSOLETE ) { last; } } } $ui->progress_fin; return ( $state, @vars ); } 1; needrestart-3.11/perl/lib/NeedRestart/uCode/000077500000000000000000000000001477700625400207615ustar00rootroot00000000000000needrestart-3.11/perl/lib/NeedRestart/uCode/AMD.pm000066400000000000000000000132731477700625400217260ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 package is based on the result of the following paper: # # Security Analysis of x86 Processor Microcode # Daming D. Chen # Gail-Joon Ahn # # https://www.dcddcc.com/docs/2014_paper_microcode.pdf # package NeedRestart::uCode::AMD; use strict; use warnings; use NeedRestart::uCode; use NeedRestart::Utils; use File::Basename; use POSIX qw(uname); use Locale::TextDomain 'needrestart'; my $LOGPREF = '[uCode/AMD]'; 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); } my $_ucodes; sub _scan_ucodes { my $debug = shift; # scan AMD ucode files foreach my $fn () { my $bn = basename( $fn, '.bin' ); my $fh; unless ( open( $fh, '<:raw', $fn ) ) { warn "$LOGPREF Failed to open ucode source file '$fn': $!\n"; next; } my @stat = stat($fh); my $fpos = read( $fh, my $buf, 12 ); my ( $hdr_magic, $hdr_type, $hdr_size ) = unpack( 'a4VV', $buf ); if ( $hdr_magic ne "DMA\0" ) { warn "$LOGPREF Invalid magic header ($hdr_magic)!\n"; next; } if ( $hdr_type != 0 ) { warn "$LOGPREF Unsupported table type $hdr_type!\n"; next; } for ( ; $fpos < $hdr_size ; ) { $fpos += read( $fh, $buf, 16 ); my ( $pkg_cpuid, $pkg_errmask, $pkg_errcomp, $pkg_prid, $pkg_unk ) = unpack( 'VVVvv', $buf ); if ( $pkg_cpuid > 0 ) { $_ucodes->{cpuid}->{$pkg_cpuid} = $pkg_prid; printf STDERR "$LOGPREF cpuid 0x%08x: found processor id 0x%08x\n", $pkg_cpuid, $pkg_prid if ($debug); } } for ( ; $fpos < $stat[7] ; ) { $fpos += read( $fh, $buf, 8 ); my ( $upd_type, $upd_size ) = unpack( 'VV', $buf ); $fpos += read( $fh, $buf, $upd_size ); my ( $pat_date, $pat_pid, $pat_did, $pat_dlen, $pat_iflg, $pat_dchk, $pat_ndid, $pat_sdid, $pat_prid ) = unpack( 'VVvCCVVVv', $buf ); $_ucodes->{prid}->{$pat_prid} = $pat_pid; printf STDERR "$LOGPREF processor id 0x%08x: available ucode 0x%08x\n", $pat_prid, $pat_pid if ($debug); } } } sub nr_ucode_check_real { my $debug = shift; my $ui = shift; my $info = shift; # check for AMD cpu unless ( defined( $info->{vendor_id} ) && $info->{vendor_id} eq 'AuthenticAMD' ) { die "$LOGPREF #$info->{processor} cpu vendor id mismatch\n"; } # get CPUID using kernel module my $cpuid; if ( open( my $fh, '<:raw', "/dev/cpu/$info->{processor}/cpuid" ) ) { seek( $fh, 1, 0 ); read( $fh, my $eax, 16 ); close($fh); $cpuid = unpack( 'V', $eax ); printf( STDERR "$LOGPREF #$info->{processor} cpuid 0x%08x (/dev/cpu/$info->{processor}/cpuid)\n", $cpuid ) if ($debug); } else { warn "$LOGPREF #$info->{processor} Failed to open /dev/cpu/$info->{processor}/cpuid (Missed \`modprobe cpuid\`?): $!\n" if ($debug); } # get CPUID from /proc/cpuinfo my $family = int( $info->{'cpu family'} ); my $xfamily = 0; if ( $family > 0xf ) { $xfamily = $family - 0xf; $family = 0xf; } my $model = int( $info->{model} ); my $xmodel = $model >> 4; $model = $model & 0xf; my $stepping = int( $info->{stepping} ); my $eax = ( ( ( $xfamily & 0xff ) << 20 ) + ( ( $xmodel & 0xf ) << 16 ) + ( ( $family & 0xf ) << 8 ) + ( ( $model & 0xf ) << 4 ) + ( ( $stepping & 0xf ) << 0 ) ); printf( STDERR "$LOGPREF #$info->{processor} cpuid 0x%08x (/proc/cpuinfo)\n", $eax ) if ($debug); if ($cpuid) { if ( $cpuid != $eax ) { warn "$LOGPREF #$info->{processor} CPUID mismatch detected!\n" if ($debug); } } else { $cpuid = $eax; } # get microcode version of cpu my $ucode = hex( $info->{microcode} ); printf( STDERR "$LOGPREF #$info->{processor} running ucode 0x%08x\n", $ucode ) if ($debug); unless ( defined($_ucodes) ) { _scan_ucodes( $debug ); } my %vars = ( CURRENT => sprintf( "0x%08x", $ucode ), ); # check for microcode updates if ( exists( $_ucodes->{cpuid}->{$cpuid} ) ) { my $prid = $_ucodes->{cpuid}->{$cpuid}; if ( exists( $_ucodes->{prid}->{$prid} ) ) { $vars{AVAIL} = sprintf( "0x%08x", $_ucodes->{prid}->{$prid} ); print STDERR "$LOGPREF #$info->{processor} found ucode $vars{AVAIL}\n" if ($debug); } } return %vars; } 1; needrestart-3.11/perl/lib/NeedRestart/uCode/Intel.pm000066400000000000000000000054271477700625400224020ustar00rootroot00000000000000# needrestart - Restart daemons after library updates. # # Authors: # Thomas Liske # # Copyright Holder: # 2013 - 2025 (C) Thomas Liske # # 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 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`); } my $_avail; sub nr_ucode_check_real { my $debug = shift; my $ui = shift; my $info = shift; my %vars; # check for Intel cpu unless ( defined( $info->{vendor_id} ) && $info->{vendor_id} eq 'GenuineIntel' ) { die "$LOGPREF #$info->{processor} cpu vendor id mismatch\n"; } # get current microcode revision if ( defined( $info->{microcode} ) ) { $vars{CURRENT} = sprintf( "0x%04x", hex( $info->{microcode} ) ); print STDERR "$LOGPREF #$info->{processor} current revision: $vars{CURRENT}\n" if ($debug); } else { print STDERR "$LOGPREF #$info->{processor} current microcode revision not found in /proc/cpuinfo: $!\n" if ($debug); return %vars; } # find and cache microcode updates unless ( defined($_avail) ) { my $fh = nr_fork_pipe( $debug, NRM_INTEL_HELPER, $debug ); while (<$fh>) { if (/\s*\d+(\/\d+)?: sig.+, rev (0x[\da-f]+),/) { $_avail = sprintf( "0x%04x", hex($2) ); print STDERR "$LOGPREF #$info->{processor} available revision: $2\n" if ($debug); next; } } close($fh); } $vars{AVAIL} = $_avail if ( defined($_avail) ); return %vars; } 1; needrestart-3.11/po/000077500000000000000000000000001477700625400144105ustar00rootroot00000000000000needrestart-3.11/po/debconf000077700000000000000000000000001477700625400205162../ex/debconf/poustar00rootroot00000000000000needrestart-3.11/po/needrestart-notify/000077500000000000000000000000001477700625400202365ustar00rootroot00000000000000needrestart-3.11/po/needrestart-notify/Makefile000066400000000000000000000004741477700625400217030ustar00rootroot00000000000000TEXTDOMAIN:=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.11/po/needrestart-notify/cs.po000066400000000000000000000040541477700625400212060ustar00rootroot00000000000000# 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. # 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: 2018-09-26 13:11+0200\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 2.0.6\n" "Last-Translator: \n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "Language: cs\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 "" "Ve vašem sezení jsou spuštěné zastaralé binárky nebo knihovny, jak je " "vypsáno níže.\n" "Zvažte odhlášení a přihlášení se znovu nebo restart procesů, kterých se týká!" #: 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 "" "Ve vašem sezení na stroji $_NR_FQDN ($NR_SESSION) jsou spuštěné zastaralé " "binárky nebo knihovny, jak je vypsáno níže." #: ex/notify.d/600-mail:44 msgid "Please consider a relogin or restart of the affected processes!" msgstr "" "Zvažte odhlášení a přihlášení se znovu nebo restart procesů, kterých se týká!" #: ex/notify.d/400-notify-send:44 msgid "Relogin or restarts required!" msgstr "Je třeba se odhlásit a znovu přihlásit nebo restartovat!" #: 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 "" "Ve vašem sezení jsou spuštěné zastaralé binárky nebo knihovny, jak je " "vypsáno níže.\n" "Please consider a relogin or restart of the affected processes!" needrestart-3.11/po/needrestart-notify/de.po000066400000000000000000000033171477700625400211720ustar00rootroot00000000000000#, 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.11/po/needrestart-notify/messages.pot000066400000000000000000000025471477700625400226010ustar00rootroot00000000000000# 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.11/po/needrestart-notify/ru.po000066400000000000000000000047701477700625400212340ustar00rootroot00000000000000# 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.11/po/needrestart-notify/zh_TW.po000066400000000000000000000036361477700625400216410ustar00rootroot00000000000000# Traditional Chinese translation for needrestart-notify. # Copyright (C) 2024 THE needrestart-notify'S COPYRIGHT HOLDER # This file is distributed under the same license as the needrestart-notify package. # Peter Dave Hello , 2024. # 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: 2024-11-22 19:25+0800\n" "Last-Translator: Peter Dave Hello \n" "Language-Team: Traditional Chinese\n" "Language: zh_TW\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 "" "您的連線階段正在執行以下過時的執行檔或涵式庫。\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.11/po/needrestart/000077500000000000000000000000001477700625400167305ustar00rootroot00000000000000needrestart-3.11/po/needrestart/Makefile000066400000000000000000000004651477700625400203750ustar00rootroot00000000000000TEXTDOMAIN:=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.11/po/needrestart/cs.po000066400000000000000000000161361477700625400177040ustar00rootroot00000000000000# 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. # 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: 2018-09-26 13:06+0200\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 2.0.6\n" "Last-Translator: \n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "Language: cs\n" #: needrestart:234 msgid "Available UI packages:" msgstr "Balíčky uživatelského rozhraní k dispozici:" #: needrestart:438 msgid "Scanning processes..." msgstr "Skenování procesů…" #: needrestart:584 msgid "Scanning candidates..." msgstr "Skenování kandidátů…" #: needrestart:758 msgid "Your outdated processes:" msgstr "Zastaralé procesy:" #: needrestart:822 msgid "Running kernel seems to be up-to-date." msgstr "Jádro se kterým je nyní spuštěno se zdá být aktuální." #: needrestart:822 msgid "Running kernel seems to be up-to-date (ABI upgrades are not detected)." msgstr "" "Jádro, se kterým je nyní spuštěno se zdá být aktuální (nezjištěny " "aktualizace ABI rozhraní)." #: needrestart:826 needrestart:840 msgid "an outdated kernel image" msgstr "zastaralý obraz jádra" #: needrestart:831 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} and there is an ABI " "compatible upgrade pending." msgstr "" "Nyní provozováno na verzi jádra {kversion} a přitom je k dispozici " "aktualizace, která zachovává kompatibilní ABI rozhraní." #: needrestart:845 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} which is not the expected " "kernel version {eversion}." msgstr "" "Nyní provozovaná verze jádra je {kversion}, což není očekávaná verze " "{eversion}." #: needrestart:856 msgid "Failed to retrieve available kernel versions." msgstr "Nepodařilo se zjistit jaké verze jádra jsou k dispozici." #: needrestart:895 msgid "The processor microcode seems to be up-to-date." msgstr "Mikrokód procesoru se zdá být aktuální." #: needrestart:899 msgid "outdated processor microcode" msgstr "zastaralý mikrokód procesoru" #: needrestart:907 msgid "Failed to check for processor microcode upgrades." msgstr "" "Nepodařilo se zjistit dostupnost případných aktualizací mikrokódu procesoru." #: needrestart:916 msgid "No services need to be restarted." msgstr "Není třeba restartovat žádné služby." #: needrestart:925 msgid "outdated binaries" msgstr "zastaralé binárky" #: needrestart:931 needrestart:1041 msgid "Services to be restarted:" msgstr "Služby které je třeba restartovat:" #: needrestart:932 needrestart:1040 msgid "Restarting services..." msgstr "Restartování služeb…" #: needrestart:995 needrestart:1067 msgid "Service restarts being deferred:" msgstr "Restarty služeb, které jsou odložené:" #: needrestart:1010 needrestart:1081 msgid "Service restarts being refused by systemd:" msgstr "Restarty služeb, odmítnuté systemd:" #: needrestart:1095 msgid "No containers need to be restarted." msgstr "Žádné kontejnery není třeba restartovat." #: needrestart:1104 msgid "outdated containers" msgstr "zastaralé kontejnery" #: needrestart:1109 needrestart:1161 msgid "Containers to be restarted:" msgstr "Kontejnery které je třeba restartovat:" #: needrestart:1110 needrestart:1160 msgid "Restarting containers..." msgstr "Restartování kontejnerů…" #: needrestart:1151 msgid "Container restarts being deferred:" msgstr "Restarty kontejnerů, které jsou odložené:" #: needrestart:1174 msgid "No user sessions are running outdated binaries." msgstr "V žádném z uživatelských sezení nejsou spuštěné zastaralé binárky." #: needrestart:1183 msgid "outdated sessions" msgstr "zastaralé relace" #: needrestart:1186 msgid "User sessions running outdated binaries:" msgstr "Uživatel který má spuštěné zastaralé binárky:" #: needrestart:1234 msgid "and" msgstr "a" #: perl/lib/NeedRestart/Kernel/Linux.pm:136 msgid "Scanning linux images..." msgstr "Skenování obrazů linuxového jádra…" #: perl/lib/NeedRestart/Kernel/kFreeBSD.pm:49 msgid "Scanning kfreebsd images..." msgstr "Skenování obrazů kfreebsd…" #: 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 "" "Pending kernel upgrade!\n" "\n" "Spuštěno s verzí jádra:\n" " {kversion}\n" "\n" "Diagnostika:\n" " {message}\n" "\n" "Restart systému pro načtení nového jádra nebude obsloužen automaticky, takže " "byste měli zvážit restart stroje. [Return]\n" #: perl/lib/NeedRestart/UI/stdio.pm:54 msgid "The currently running kernel has an ABI compatible upgrade pending." msgstr "" "Pro jádro, na kterém je nyní provozováno, je k dispozici aktualizace, která " "zachovává kompatibilní ABI rozhraní." #: perl/lib/NeedRestart/UI/stdio.pm:62 #, perl-brace-format msgid "" "The currently running kernel version is not the expected kernel version " "{eversion}." msgstr "" "Verze jádra, se kterou je nyní spuštěno není očekávaná verze {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" "Na tomto systému je sputěno {ehint}. Další podrobnosti získáte spuštěním " "„needrestart -m a“.\n" "\n" "Měli byste zvážit restart!\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 "" "Čekající aktualizace mikrokódu procesoru!\n" "\n" "Diagnostika:\n" " Nyní je provozována revize mikrokódu procesoru {current}, což není " "očekávaná revize {avail}.\n" "\n" "Restart systému pro načtení nového mikrokódu procesoru nebude obsloužen " "automaticky, takže byste měli zvážit restart. [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 "" " (Y)es – restartovat tuto službu\n" " (N)o – nerestartovat tuto službu\n" " (A)uto – automaticky restartovat všechny zbývající služby\n" " (S)top – zastavit restartování sluřeb\n" "\n" #: perl/lib/NeedRestart/UI/stdio.pm:189 #, perl-brace-format msgid "Restart «{rc}»?" msgstr "Restartovat „{rc}“?" needrestart-3.11/po/needrestart/de.po000066400000000000000000000150611477700625400176630ustar00rootroot00000000000000msgid "" 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.11/po/needrestart/messages.pot000066400000000000000000000110511477700625400212610ustar00rootroot00000000000000# 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.11/po/needrestart/ru.po000066400000000000000000000145721477700625400177270ustar00rootroot00000000000000msgid "" 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}»?" needrestart-3.11/po/needrestart/zh_TW.po000066400000000000000000000151511477700625400203260ustar00rootroot00000000000000# Traditional Chinese translation for needrestart. # Copyright (C) 2024 THE needrestart'S COPYRIGHT HOLDER # This file is distributed under the same license as the needrestart package. # Peter Dave Hello , 2024. # 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: 2024-11-22 19:25+0800\n" "Last-Translator: Peter Dave Hello \n" "Language-Team: Traditional Chinese\n" "Language: zh_TW\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 "目前運作中的核心似乎是最新版 (未偵測到 ABI 升級)。" #: 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 "目前運作中的核心版本為 {kversion},有一個 ABI 相容的升級待處理。" #: needrestart:845 #, perl-brace-format msgid "" "The currently running kernel version is {kversion} which is not the expected " "kernel version {eversion}." msgstr "目前運作中的核心版本為 {kversion},與預期的核心版本 {eversion} 不符。" #: 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 "被 systemd 拒絕重新啟動的服務:" #: 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 "正在掃描 Linux 映像檔..." #: perl/lib/NeedRestart/Kernel/kFreeBSD.pm:49 msgid "Scanning kfreebsd images..." msgstr "正在掃描 kFreeBSD 映像檔..." #: 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 "" "核心升級待處理!\n" "\n" "運作中的核心版本:\n" " {kversion}\n" "\n" "診斷:\n" " {message}\n" "\n" "系統不會自動重新啟動來載入新核心,建議您手動重新開機。 [Enter]\n" #: perl/lib/NeedRestart/UI/stdio.pm:54 msgid "The currently running kernel has an ABI compatible upgrade pending." msgstr "目前運作中的核心有一個 ABI 相容的升級待處理。" #: perl/lib/NeedRestart/UI/stdio.pm:62 #, perl-brace-format msgid "" "The currently running kernel version is not the expected kernel version " "{eversion}." msgstr "目前運作中的核心版本與預期的核心版本 {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" "此系統執行 {ehint}。欲取得更多資訊,請執行 «needrestart -m a»。\n" "\n" "建議您手動重新開機!\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 "" "處理器微碼升級待處理!\n" "\n" "診斷:\n" " 目前執行中的處理器微碼版本為 {current},與預期的微碼版本 {avail} 不符。\n" "\n" "系統不會自動重新啟動來載入新的處理器微碼,建議您手動重新開機。 [Enter]\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 "" " (Y)es - 重新啟動此服務\n" " (N)o - 不要重新啟動此服務\n" " (A)uto - 自動重新啟動所有剩餘服務\n" " (S)top - 停止重新啟動服務\n" "\n" #: perl/lib/NeedRestart/UI/stdio.pm:189 #, perl-brace-format msgid "Restart «{rc}»?" msgstr "要重新啟動 «{rc}» 嗎?"