free: Show single line statistics

Added the -L --line option to free to show a small
set of memory statistics on a single line of 80 characters.
Largely based on the work of @Ulenrich1 and updated to
the new API.

References:
 procps-ng/procps#156

Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
Craig Small 2023-05-02 20:32:38 +10:00
parent 4a315c9230
commit b31ac2dcce
4 changed files with 34 additions and 2 deletions

1
NEWS
View File

@ -2,6 +2,7 @@ procps-ng-NEXT
--------------- ---------------
* library (API & ABI unchanged) * library (API & ABI unchanged)
tolerates all potential 'cpuinfo' formats issue #272 tolerates all potential 'cpuinfo' formats issue #272
* free: -L one line output issue #156
* pgrep: Use only --signal option for signal Debian #1031765 * pgrep: Use only --signal option for signal Debian #1031765
* tests: dont compare floats with == issue #271 * tests: dont compare floats with == issue #271
* top: bad command line arguments yield EXIT_FAILURE issue #273 * top: bad command line arguments yield EXIT_FAILURE issue #273

View File

@ -11,7 +11,7 @@
.\" (at your option) any later version. .\" (at your option) any later version.
.\" .\"
.\" .\"
.TH FREE 1 "2023-01-16" "procps-ng" "User Commands" .TH FREE 1 "2023-05-02" "procps-ng" "User Commands"
.SH NAME .SH NAME
free \- Display amount of free and used memory in the system free \- Display amount of free and used memory in the system
.SH SYNOPSIS .SH SYNOPSIS
@ -120,6 +120,11 @@ option.
\fB\-l\fR, \fB\-\-lohi\fR \fB\-l\fR, \fB\-\-lohi\fR
Show detailed low and high memory statistics. Show detailed low and high memory statistics.
.TP .TP
\fB\-L\fR, \fB\-\-line\fR
Show output on a single line, often used with the
.B \-s
option to show memory statistics repeatedly.
.TP
\fB\-s\fR, \fB\-\-seconds\fR \fIdelay\fR \fB\-s\fR, \fB\-\-seconds\fR \fIdelay\fR
Continuously display the result \fIdelay\fR seconds Continuously display the result \fIdelay\fR seconds
apart. You may actually specify any floating point number for apart. You may actually specify any floating point number for

View File

@ -53,6 +53,7 @@
#define FREE_REPEAT (1 << 6) #define FREE_REPEAT (1 << 6)
#define FREE_REPEATCOUNT (1 << 7) #define FREE_REPEATCOUNT (1 << 7)
#define FREE_COMMITTED (1 << 8) #define FREE_COMMITTED (1 << 8)
#define FREE_LINE (1 << 9)
struct commandline_arguments { struct commandline_arguments {
int exponent; /* demanded in kilos, magas... */ int exponent; /* demanded in kilos, magas... */
@ -86,6 +87,7 @@ static void __attribute__ ((__noreturn__))
fputs(_(" -h, --human show human-readable output\n"), out); fputs(_(" -h, --human show human-readable output\n"), out);
fputs(_(" --si use powers of 1000 not 1024\n"), out); fputs(_(" --si use powers of 1000 not 1024\n"), out);
fputs(_(" -l, --lohi show detailed low and high memory statistics\n"), out); fputs(_(" -l, --lohi show detailed low and high memory statistics\n"), out);
fputs(_(" -L, --line show output on a single line\n"), out);
fputs(_(" -t, --total show total for RAM + swap\n"), out); fputs(_(" -t, --total show total for RAM + swap\n"), out);
fputs(_(" -v, --committed show committed memory and commit limit\n"), out); fputs(_(" -v, --committed show committed memory and commit limit\n"), out);
fputs(_(" -s N, --seconds N repeat printing every N seconds\n"), out); fputs(_(" -s N, --seconds N repeat printing every N seconds\n"), out);
@ -237,6 +239,7 @@ int main(int argc, char **argv)
{ "human", no_argument, NULL, 'h' }, { "human", no_argument, NULL, 'h' },
{ "si", no_argument, NULL, SI_OPTION }, { "si", no_argument, NULL, SI_OPTION },
{ "lohi", no_argument, NULL, 'l' }, { "lohi", no_argument, NULL, 'l' },
{ "line", no_argument, NULL, 'L' },
{ "total", no_argument, NULL, 't' }, { "total", no_argument, NULL, 't' },
{ "committed", no_argument, NULL, 'v' }, { "committed", no_argument, NULL, 'v' },
{ "seconds", required_argument, NULL, 's' }, { "seconds", required_argument, NULL, 's' },
@ -260,7 +263,7 @@ int main(int argc, char **argv)
textdomain(PACKAGE); textdomain(PACKAGE);
atexit(close_stdout); atexit(close_stdout);
while ((c = getopt_long(argc, argv, "bkmghltvc:ws:V", longopts, NULL)) != -1) while ((c = getopt_long(argc, argv, "bkmghlLtvc:ws:V", longopts, NULL)) != -1)
switch (c) { switch (c) {
case 'b': case 'b':
check_unit_set(&unit_set); check_unit_set(&unit_set);
@ -320,6 +323,9 @@ int main(int argc, char **argv)
case 'l': case 'l':
flags |= FREE_LOHI; flags |= FREE_LOHI;
break; break;
case 'L':
flags |= FREE_LINE;
break;
case 't': case 't':
flags |= FREE_TOTAL; flags |= FREE_TOTAL;
break; break;
@ -367,6 +373,21 @@ int main(int argc, char **argv)
_("Unable to create meminfo structure")); _("Unable to create meminfo structure"));
} }
do { do {
if ( flags & FREE_LINE ) {
/* Translation Hint: These are shortened column headers
* that are all 7 characters long. Use spaces and right
* align if the translation is shorter.
*/
printf("%s %11s ", _("SwapUse"), scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_USED, ul_int), flags, args));
printf("%s %11s ", _("CachUse"), scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_BUFFERS, ul_int) +
MEMINFO_GET(mem_info, MEMINFO_MEM_CACHED_ALL, ul_int), flags, args));
printf("%s %11s ", _(" MemUse"), scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_USED, ul_int), flags, args));
printf("%s %11s ", _("MemFree"), scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_FREE, ul_int), flags, args));
if ( (flags & FREE_REPEAT) == 0 )
printf("\n");
else if ( args.repeat_counter == 1 )
printf("\n");
} else {
/* Translation Hint: You can use 9 character words in /* Translation Hint: You can use 9 character words in
* the header, and the words need to be right align to * the header, and the words need to be right align to
* beginning of a number. */ * beginning of a number. */
@ -441,6 +462,7 @@ int main(int argc, char **argv)
printf("\n"); printf("\n");
} }
} /* end else of if FREE_LINE */
fflush(stdout); fflush(stdout);
if (flags & FREE_REPEATCOUNT) { if (flags & FREE_REPEATCOUNT) {
args.repeat_counter--; args.repeat_counter--;

View File

@ -55,3 +55,7 @@ set test "free with positive repeat count"
spawn $free -c 2 spawn $free -c 2
expect_continue "$test" "^${free_header}" expect_continue "$test" "^${free_header}"
expect_pass "$test" "${free_header}" expect_pass "$test" "${free_header}"
set test "free with single line"
spawn $free -L
expect_pass "$test" "^SwapUse\\s+\\d+\\s+CachUse\\s+\\d+\\s+MemUse\\s+\\d+\\s+MemFree\\s+\\d+\\s*$"