Differences between version 15 and revision by previous author of PerlOneLiners.
Other diffs: Previous Major Revision, Previous Revision, or view the Annotated Edit History
Newer page: | version 15 | Last edited on Friday, April 9, 2004 11:30:40 am | by AristotlePagaltzis | Revert |
Older page: | version 13 | Last edited on Thursday, April 8, 2004 5:11:21 pm | by JohnMcPherson | Revert |
@@ -29,13 +29,36 @@
You can use any punctuation as the separator in an __s///__ command, and if you have backslashes or even need literal slashes in your pattern then doing this can increase clarity.
!! List all currently running processes
- perl -pe 'BEGIN {undef$/;chdir"/proc";@ARGV=sort{$a<=>$b}glob("*/cmdline")}
- $ARGV=~/(\d+)/;print "$1\t";s@\0@ @g;$_.="\n";'
-This prints the process ID and command line of every running process on the system (except some "special" kernel processes that lie about/don't have command lines). You might want such a command if you suspect a rootkit or something similar has been installed, and you can't trust your "ps" binary
.
+This is useful if you suspect that ps(1) is not reliable, whether due to a RootKit or some other cause. It
prints the process ID and command line of every running process on the system (except some "special" kernel processes that lie about/don't have command lines).
-Basically, this runs
a loop over all
the files in
/proc/*/cmdline, printing the content
of those
files (after printing
the leading
digits in
the filename, and replacing
null characters with
a space)
. "$/" is a special variable used for
the end
-of
-line marker
, and it needs
to be unset so
that even
the empty/unreadable files still cause
the loop to print out
the filename
. The __-p
__ switch for perl means do
the loop
, using the
input of the rest of the arguments
(assumed
to be filenames)
. We cheat
and manually assign @ARGV
in the BEGIN{..} block
. Also
, we need
to tell sort
to use
a numeric comparison
(<=
>) instead of the default string comparison
.
+ perl -0777 -pe 'BEGIN { chdir "/proc"; @ARGV = sort { $
a <=> $b } glob("*/cmdline") }
+ $ARGV =~ m!^(\d+)/!; print "$1\t"; s/\/ /g; $_ .= "\n";'
+
+It runs an implicit
loop over the __
/proc/*/cmdline__ files
, by priming __@ARGV__ with a list
of files sorted numerically
(which needs to be done explicitly using __<=>__ -- the default sort is [ASCII]betical) and then employing the __-p__ switch. __-0777__ forces files to be slurped wholesale. Per file,
the digits that lead
the filename are printed
, followed by a tab. Since a
null separates the arguments in these files, all of them are replaced by spaces to make the output printable. Finally,
a newline is appended
. The print call implicit in the __-p__ switch then takes care of outputting the massaged command line.
+
+
+!! List all currently running processes, but nicer
+
+See above for what this does. The ''how'' is different, though.
+
+ perl -MFile::Slurp -0le 'for(sort { $a <=> $b } grep !/\D/, read_dir
"/proc")
+ { @ARGV = "/proc/
$_
/cmdline
"; printf " %6g %s\n", $_, join(" ", <>); }'
+
+This time the loop
is explicit. Again, there are two parts to
the program
-- selecting files and doing [IO] on them.
+
+To read the directory
, a convenience function is pulled in from the File::Slurp module, loaded using the __-M__ switch. The module has been part of the core distribution since Perl 5.8.. Reading a directory manually is straightforward but the code would be longer
and clumsier.
+
+Selecting the files is pretty simple, if a little obtuse:
it's done by reading the contents of __/proc__, then using __grep !/D/__
to reject any entries
that contain non-digit characters from
the list. The results,are then sorted numerically, done explicitly using __<=>__ because
the default sort is [ASCII]betical. Each entry is then concatenated into a full path and stuck into __@ARGV__ one by one, from where
the __<>__ "diamond operator" will pick it up, auto-open it and read it for us, even autoreporting any errors in a nicely verbose format.
+
+Producing human-readable output is a little more involved, using some switches to abbreviate a bit of magic
. The __-
__ switch sets
the __$/__ variable: here
, because it is not followed by a digit, it sets it to a null character. This means that null characters will be regarded as line separators on
input. The __-l__ switch has two effects,
of which only one is relevant to us: it automatically __chomp()__s lines read using
the diamond operator.
(The other is
to set the __$\__ variable, which we aren't interested in or affected by
.)
+
+;: Note that the __-__
and __-l__ switches are order sensitive both
in syntax and semantics
. We order them for syntax here, because they can both accept an octal number as input
, but
we don't
to pass one
to either of them (particularly, __-__ will be mistaken for
a digit parameter to __-l__ if we turn them around).
+
+Together, these switches effectively mean that we get null terminated lines from files, with the nulls removed on input. So we get the command line arguments listed in a __/proc/*/cmdline__ file as nice list of separate strings. And because __join
()__ expects a list, __
<>__ returns all "lines" (ie command line arguments
) at once, which __join()__ then dutifully puts together with spaces between.
+
+The printf(3) is straightforward
.
----
AddToMe