From 47264b161d040b04d0ed2dedf06f9a73d8c8a7bc Mon Sep 17 00:00:00 2001 From: Weifeng Su Date: Wed, 8 Feb 2023 22:06:43 +0800 Subject: [PATCH] Upgrade to version 3.14 Signed-off-by: Weifeng Su --- lgpl-2.1.txt | 502 --------------------------------------------------- ps_mem.1 | 45 ----- ps_mem.py | 493 -------------------------------------------------- ps_mem.spec | 23 +-- v3.14.tar.gz | Bin 0 -> 18539 bytes 5 files changed, 10 insertions(+), 1053 deletions(-) delete mode 100644 lgpl-2.1.txt delete mode 100644 ps_mem.1 delete mode 100644 ps_mem.py create mode 100644 v3.14.tar.gz diff --git a/lgpl-2.1.txt b/lgpl-2.1.txt deleted file mode 100644 index 4362b49..0000000 --- a/lgpl-2.1.txt +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/ps_mem.1 b/ps_mem.1 deleted file mode 100644 index 12bf337..0000000 --- a/ps_mem.1 +++ /dev/null @@ -1,45 +0,0 @@ -.\" Simple man page to ps_mem script -.\" Contact fholec@redhat.com -.TH ps_mem 1 "04 October 2014" "" "" -.SH NAME -ps_mem \- Memory profiling tool -.SH SYNOPSIS -.B ps_mem [OPTION]... -.SH DESCRIPTION -Display the core memory used per program (not per process) -.br -.PP -In detail it reports: -.br -.PP -.RS -sum (private RAM for program processes) + -.br -sum (shared RAM for program processes) -.br -.RE -.PP -The shared RAM is problematic to calculate, and the tool automatically selects the most accurate method available for the running kernel. -.SH OPTIONS -.TP -\-h \-\-help -Show help message -.TP -\-p PID[,PID2,...PIDN] -Show memory consumption for the specified processes -.TP -\-s \-\-split\-args -Show and separate memory usage entries by command line arguments -and not just the program name. -.TP -\-t \-\-total -Only display the total number of bytes for the selected processes -.TP -\-w N -Report memory consumption every N seconds -.\".SH SEE ALSO -.\" -.\".SH BUGS -.\"No known bugs for this template, except you might want to replace the quotes if you copy from my blog. -.SH AUTHOR -Pádraig Brady diff --git a/ps_mem.py b/ps_mem.py deleted file mode 100644 index 8e30bce..0000000 --- a/ps_mem.py +++ /dev/null @@ -1,493 +0,0 @@ -#!/usr/bin/env python - -# Try to determine how much RAM is currently being used per program. -# Note per _program_, not per process. So for example this script -# will report RAM used by all httpd process together. In detail it reports: -# sum(private RAM for program processes) + sum(Shared RAM for program processes) -# The shared RAM is problematic to calculate, and this script automatically -# selects the most accurate method available for your kernel. - -# Licence: LGPLv2 -# Author: P@draigBrady.com -# Source: http://www.pixelbeat.org/scripts/ps_mem.py - -# V1.0 06 Jul 2005 Initial release -# V1.1 11 Aug 2006 root permission required for accuracy -# V1.2 08 Nov 2006 Add total to output -# Use KiB,MiB,... for units rather than K,M,... -# V1.3 22 Nov 2006 Ignore shared col from /proc/$pid/statm for -# 2.6 kernels up to and including 2.6.9. -# There it represented the total file backed extent -# V1.4 23 Nov 2006 Remove total from output as it's meaningless -# (the shared values overlap with other programs). -# Display the shared column. This extra info is -# useful, especially as it overlaps between programs. -# V1.5 26 Mar 2007 Remove redundant recursion from human() -# V1.6 05 Jun 2007 Also report number of processes with a given name. -# Patch from riccardo.murri@gmail.com -# V1.7 20 Sep 2007 Use PSS from /proc/$pid/smaps if available, which -# fixes some over-estimation and allows totalling. -# Enumerate the PIDs directly rather than using ps, -# which fixes the possible race between reading -# RSS with ps, and shared memory with this program. -# Also we can show non truncated command names. -# V1.8 28 Sep 2007 More accurate matching for stats in /proc/$pid/smaps -# as otherwise could match libraries causing a crash. -# Patch from patrice.bouchand.fedora@gmail.com -# V1.9 20 Feb 2008 Fix invalid values reported when PSS is available. -# Reported by Andrey Borzenkov -# V3.6 16 Oct 2015 -# http://github.com/pixelb/scripts/commits/master/scripts/ps_mem.py - -# Notes: -# -# All interpreted programs where the interpreter is started -# by the shell or with env, will be merged to the interpreter -# (as that's what's given to exec). For e.g. all python programs -# starting with "#!/usr/bin/env python" will be grouped under python. -# You can change this by using the full command line but that will -# have the undesirable affect of splitting up programs started with -# differing parameters (for e.g. mingetty tty[1-6]). -# -# For 2.6 kernels up to and including 2.6.13 and later 2.4 redhat kernels -# (rmap vm without smaps) it can not be accurately determined how many pages -# are shared between processes in general or within a program in our case: -# http://lkml.org/lkml/2005/7/6/250 -# A warning is printed if overestimation is possible. -# In addition for 2.6 kernels up to 2.6.9 inclusive, the shared -# value in /proc/$pid/statm is the total file-backed extent of a process. -# We ignore that, introducing more overestimation, again printing a warning. -# Since kernel 2.6.23-rc8-mm1 PSS is available in smaps, which allows -# us to calculate a more accurate value for the total RAM used by programs. -# -# Programs that use CLONE_VM without CLONE_THREAD are discounted by assuming -# they're the only programs that have the same /proc/$PID/smaps file for -# each instance. This will fail if there are multiple real instances of a -# program that then use CLONE_VM without CLONE_THREAD, or if a clone changes -# its memory map while we're checksumming each /proc/$PID/smaps. -# -# I don't take account of memory allocated for a program -# by other programs. For e.g. memory used in the X server for -# a program could be determined, but is not. -# -# FreeBSD is supported if linprocfs is mounted at /compat/linux/proc/ -# FreeBSD 8.0 supports up to a level of Linux 2.6.16 - -import getopt -import time -import errno -import os -import sys - -# The following exits cleanly on Ctrl-C or EPIPE -# while treating other exceptions as before. -def std_exceptions(etype, value, tb): - sys.excepthook = sys.__excepthook__ - if issubclass(etype, KeyboardInterrupt): - pass - elif issubclass(etype, IOError) and value.errno == errno.EPIPE: - pass - else: - sys.__excepthook__(etype, value, tb) -sys.excepthook = std_exceptions - -# -# Define some global variables -# - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") / 1024 #KiB -our_pid = os.getpid() - -have_pss = 0 - -class Proc: - def __init__(self): - uname = os.uname() - if uname[0] == "FreeBSD": - self.proc = '/compat/linux/proc' - else: - self.proc = '/proc' - - def path(self, *args): - return os.path.join(self.proc, *(str(a) for a in args)) - - def open(self, *args): - try: - if sys.version_info < (3,): - return open(self.path(*args)) - else: - return open(self.path(*args), errors='ignore') - except (IOError, OSError): - val = sys.exc_info()[1] - if (val.errno == errno.ENOENT or # kernel thread or process gone - val.errno == errno.EPERM): - raise LookupError - raise - -proc = Proc() - - -# -# Functions -# - -def parse_options(): - try: - long_options = ['split-args', 'help', 'total'] - opts, args = getopt.getopt(sys.argv[1:], "shtp:w:", long_options) - except getopt.GetoptError: - sys.stderr.write(help()) - sys.exit(3) - - if len(args): - sys.stderr.write("Extraneous arguments: %s\n" % args) - sys.exit(3) - - # ps_mem.py options - split_args = False - pids_to_show = None - watch = None - only_total = False - - for o, a in opts: - if o in ('-s', '--split-args'): - split_args = True - if o in ('-t', '--total'): - only_total = True - if o in ('-h', '--help'): - sys.stdout.write(help()) - sys.exit(0) - if o in ('-p',): - try: - pids_to_show = [int(x) for x in a.split(',')] - except: - sys.stderr.write(help()) - sys.exit(3) - if o in ('-w',): - try: - watch = int(a) - except: - sys.stderr.write(help()) - sys.exit(3) - - return (split_args, pids_to_show, watch, only_total) - -def help(): - help_msg = 'Usage: ps_mem [OPTION]...\n' \ - 'Show program core memory usage\n' \ - '\n' \ - ' -h, -help Show this help\n' \ - ' -p [,pid2,...pidN] Only show memory usage PIDs in the specified list\n' \ - ' -s, --split-args Show and separate by, all command line arguments\n' \ - ' -t, --total Show only the total value\n' \ - ' -w Measure and show process memory every N seconds\n' - - return help_msg - -#(major,minor,release) -def kernel_ver(): - kv = proc.open('sys/kernel/osrelease').readline().split(".")[:3] - last = len(kv) - if last == 2: - kv.append('0') - last -= 1 - while last > 0: - for char in "-_": - kv[last] = kv[last].split(char)[0] - try: - int(kv[last]) - except: - kv[last] = 0 - last -= 1 - return (int(kv[0]), int(kv[1]), int(kv[2])) - - -#return Private,Shared -#Note shared is always a subset of rss (trs is not always) -def getMemStats(pid): - global have_pss - mem_id = pid #unique - Private_lines = [] - Shared_lines = [] - Pss_lines = [] - Rss = (int(proc.open(pid, 'statm').readline().split()[1]) - * PAGESIZE) - if os.path.exists(proc.path(pid, 'smaps')): #stat - lines = proc.open(pid, 'smaps').readlines() #open - # Note we checksum smaps as maps is usually but - # not always different for separate processes. - mem_id = hash(''.join(lines)) - for line in lines: - if line.startswith("Shared"): - Shared_lines.append(line) - elif line.startswith("Private"): - Private_lines.append(line) - elif line.startswith("Pss"): - have_pss = 1 - Pss_lines.append(line) - Shared = sum([int(line.split()[1]) for line in Shared_lines]) - Private = sum([int(line.split()[1]) for line in Private_lines]) - #Note Shared + Private = Rss above - #The Rss in smaps includes video card mem etc. - if have_pss: - pss_adjust = 0.5 # add 0.5KiB as this avg error due to trunctation - Pss = sum([float(line.split()[1])+pss_adjust for line in Pss_lines]) - Shared = Pss - Private - elif (2,6,1) <= kernel_ver() <= (2,6,9): - Shared = 0 #lots of overestimation, but what can we do? - Private = Rss - else: - Shared = int(proc.open(pid, 'statm').readline().split()[2]) - Shared *= PAGESIZE - Private = Rss - Shared - return (Private, Shared, mem_id) - - -def getCmdName(pid, split_args): - cmdline = proc.open(pid, 'cmdline').read().split("\0") - if cmdline[-1] == '' and len(cmdline) > 1: - cmdline = cmdline[:-1] - - path = proc.path(pid, 'exe') - try: - path = os.readlink(path) - # Some symlink targets were seen to contain NULs on RHEL 5 at least - # https://github.com/pixelb/scripts/pull/10, so take string up to NUL - path = path.split('\0')[0] - except OSError: - val = sys.exc_info()[1] - if (val.errno == errno.ENOENT or # either kernel thread or process gone - val.errno == errno.EPERM): - raise LookupError - raise - - if split_args: - return " ".join(cmdline) - if path.endswith(" (deleted)"): - path = path[:-10] - if os.path.exists(path): - path += " [updated]" - else: - #The path could be have prelink stuff so try cmdline - #which might have the full path present. This helped for: - #/usr/libexec/notification-area-applet.#prelink#.fX7LCT (deleted) - if os.path.exists(cmdline[0]): - path = cmdline[0] + " [updated]" - else: - path += " [deleted]" - exe = os.path.basename(path) - cmd = proc.open(pid, 'status').readline()[6:-1] - if exe.startswith(cmd): - cmd = exe #show non truncated version - #Note because we show the non truncated name - #one can have separated programs as follows: - #584.0 KiB + 1.0 MiB = 1.6 MiB mozilla-thunder (exe -> bash) - # 56.0 MiB + 22.2 MiB = 78.2 MiB mozilla-thunderbird-bin - if sys.version_info < (3,): - return cmd - else: - return cmd.encode(errors='replace').decode() - - -#The following matches "du -h" output -#see also human.py -def human(num, power="Ki", units=None): - if units is None: - powers = ["Ki", "Mi", "Gi", "Ti"] - while num >= 1000: #4 digits - num /= 1024.0 - power = powers[powers.index(power)+1] - return "%.1f %sB" % (num, power) - else: - return "%.f" % ((num * 1024) / units) - - -def cmd_with_count(cmd, count): - if count > 1: - return "%s (%u)" % (cmd, count) - else: - return cmd - -#Warn of possible inaccuracies -#2 = accurate & can total -#1 = accurate only considering each process in isolation -#0 = some shared mem not reported -#-1= all shared mem not reported -def shared_val_accuracy(): - """http://wiki.apache.org/spamassassin/TopSharedMemoryBug""" - kv = kernel_ver() - pid = os.getpid() - if kv[:2] == (2,4): - if proc.open('meminfo').read().find("Inact_") == -1: - return 1 - return 0 - elif kv[:2] == (2,6): - if os.path.exists(proc.path(pid, 'smaps')): - if proc.open(pid, 'smaps').read().find("Pss:")!=-1: - return 2 - else: - return 1 - if (2,6,1) <= kv <= (2,6,9): - return -1 - return 0 - elif kv[0] > 2 and os.path.exists(proc.path(pid, 'smaps')): - return 2 - else: - return 1 - -def show_shared_val_accuracy( possible_inacc, only_total=False ): - level = ("Warning","Error")[only_total] - if possible_inacc == -1: - sys.stderr.write( - "%s: Shared memory is not reported by this system.\n" % level - ) - sys.stderr.write( - "Values reported will be too large, and totals are not reported\n" - ) - elif possible_inacc == 0: - sys.stderr.write( - "%s: Shared memory is not reported accurately by this system.\n" % level - ) - sys.stderr.write( - "Values reported could be too large, and totals are not reported\n" - ) - elif possible_inacc == 1: - sys.stderr.write( - "%s: Shared memory is slightly over-estimated by this system\n" - "for each program, so totals are not reported.\n" % level - ) - sys.stderr.close() - if only_total and possible_inacc != 2: - sys.exit(1) - -def get_memory_usage( pids_to_show, split_args, include_self=False, only_self=False ): - cmds = {} - shareds = {} - mem_ids = {} - count = {} - for pid in os.listdir(proc.path('')): - if not pid.isdigit(): - continue - pid = int(pid) - - # Some filters - if only_self and pid != our_pid: - continue - if pid == our_pid and not include_self: - continue - if pids_to_show is not None and pid not in pids_to_show: - continue - - try: - cmd = getCmdName(pid, split_args) - except LookupError: - #operation not permitted - #kernel threads don't have exe links or - #process gone - continue - - try: - private, shared, mem_id = getMemStats(pid) - except RuntimeError: - continue #process gone - if shareds.get(cmd): - if have_pss: #add shared portion of PSS together - shareds[cmd] += shared - elif shareds[cmd] < shared: #just take largest shared val - shareds[cmd] = shared - else: - shareds[cmd] = shared - cmds[cmd] = cmds.setdefault(cmd, 0) + private - if cmd in count: - count[cmd] += 1 - else: - count[cmd] = 1 - mem_ids.setdefault(cmd, {}).update({mem_id:None}) - - #Add shared mem for each program - total = 0 - for cmd in cmds: - cmd_count = count[cmd] - if len(mem_ids[cmd]) == 1 and cmd_count > 1: - # Assume this program is using CLONE_VM without CLONE_THREAD - # so only account for one of the processes - cmds[cmd] /= cmd_count - if have_pss: - shareds[cmd] /= cmd_count - cmds[cmd] = cmds[cmd] + shareds[cmd] - total += cmds[cmd] #valid if PSS available - - sorted_cmds = sorted(cmds.items(), key=lambda x:x[1]) - sorted_cmds = [x for x in sorted_cmds if x[1]] - - return sorted_cmds, shareds, count, total - -def print_header(): - sys.stdout.write(" Private + Shared = RAM used\tProgram\n\n") - -def print_memory_usage(sorted_cmds, shareds, count, total): - for cmd in sorted_cmds: - sys.stdout.write("%9s + %9s = %9s\t%s\n" % - (human(cmd[1]-shareds[cmd[0]]), - human(shareds[cmd[0]]), human(cmd[1]), - cmd_with_count(cmd[0], count[cmd[0]]))) - if have_pss: - sys.stdout.write("%s\n%s%9s\n%s\n" % - ("-" * 33, " " * 24, human(total), "=" * 33)) - -def verify_environment(): - if os.geteuid() != 0: - sys.stderr.write("Sorry, root permission required.\n") - sys.stderr.close() - sys.exit(1) - - try: - kv = kernel_ver() - except (IOError, OSError): - val = sys.exc_info()[1] - if val.errno == errno.ENOENT: - sys.stderr.write( - "Couldn't access " + proc.path('') + "\n" - "Only GNU/Linux and FreeBSD (with linprocfs) are supported\n") - sys.exit(2) - else: - raise - -def main(): - split_args, pids_to_show, watch, only_total = parse_options() - verify_environment() - - if not only_total: - print_header() - - if watch is not None: - try: - sorted_cmds = True - while sorted_cmds: - sorted_cmds, shareds, count, total = get_memory_usage( pids_to_show, split_args ) - if only_total and have_pss: - sys.stdout.write(human(total, units=1)+'\n') - elif not only_total: - print_memory_usage(sorted_cmds, shareds, count, total) - time.sleep(watch) - else: - sys.stdout.write('Process does not exist anymore.\n') - except KeyboardInterrupt: - pass - else: - # This is the default behavior - sorted_cmds, shareds, count, total = get_memory_usage( pids_to_show, split_args ) - if only_total and have_pss: - sys.stdout.write(human(total, units=1)+'\n') - elif not only_total: - print_memory_usage(sorted_cmds, shareds, count, total) - - # We must close explicitly, so that any EPIPE exception - # is handled by our excepthook, rather than the default - # one which is reenabled after this script finishes. - sys.stdout.close() - - vm_accuracy = shared_val_accuracy() - show_shared_val_accuracy( vm_accuracy, only_total ) - -if __name__ == '__main__': main() diff --git a/ps_mem.spec b/ps_mem.spec index 5579c27..00af536 100644 --- a/ps_mem.spec +++ b/ps_mem.spec @@ -1,12 +1,10 @@ Name: ps_mem -Version: 3.6 -Release: 9 -Summary: profiling tool for memory +Version: 3.14 +Release: 1 +Summary: A utility to accurately report the in core memory usage for a program License: LGPLv2 URL: https://github.com/pixelb/ps_mem -Source0: https://raw.githubusercontent.com/pixelb/ps_mem/c80287d/ps_mem.py -Source1: http://www.gnu.org/licenses/lgpl-2.1.txt -Source2: ps_mem.1 +Source0: https://github.com/pixelb/ps_mem/archive/refs/tags/v3.14.tar.gz BuildArch: noarch BuildRequires: python3-devel %description @@ -21,15 +19,11 @@ Requires: ps_mem = %{version}-%{release} This package provides Documentation for use of ps_mem. %prep -%setup -q -T -c %{name}-%{version} -cp -p %{SOURCE0} %{name} -cp -p %{SOURCE1} LICENSE -cp -p %{SOURCE2} %{name}.1 -sed -i "s|/usr/bin/env python|%{__python3}|" %{name} -touch -r %{SOURCE0} %{name} +%autosetup -n %{name}-%{version} +sed -i "s|/usr/bin/env python|%{__python3}|" %{name}.py %install -install -Dpm755 %{name} %{buildroot}%{_bindir}/%{name} +install -Dpm755 %{name}.py %{buildroot}%{_bindir}/%{name} install -Dpm644 %{name}.1 %{buildroot}%{_mandir}/man1/%{name}.1 %files @@ -41,5 +35,8 @@ install -Dpm644 %{name}.1 %{buildroot}%{_mandir}/man1/%{name}.1 %{_mandir}/man1/%{name}.1* %changelog +* Wed Feb 8 2023 Weifeng Su 3.14-1 +- Upgrade to version 3.14 + * Thu Jun 11 2020 Jeffery.Gao - 3.6-9 - Package init diff --git a/v3.14.tar.gz b/v3.14.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..e26d320a06b69ef76744d88679fbd6334d82e679 GIT binary patch literal 18539 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 literal 0 HcmV?d00001 -- Gitee