Useful custom commands for Slackware
Here are three commands I use which I find quite useful. They all deal with finding info on the Slackware packages currently installed on the computer and are a great addition to the other package commands in Slackware (such as installpkg, removepkg, upgradepkg, etc.). These are my own homegrown commands, not copied from anywhere, which I give freely to the public domain without restriction. They are script files which can be placed in /usr/local/bin and used like any other command.
Each has a short help message to help with usage, although I will provide a quick rundown on their usage. They require the utils 'less' (less pkg) and 'egrep' (grep pkg), which may or may not be installed by default. PATTERN MATCHING <- This section has been edited. -> All the scripts now emulate the wildcard pattern matching ( * and ? ) used for filename matches. These scripts do not use true globbing, as it is sometimes called, but merely substitutes the wildcards * and ? with a regular expression equivalent, which is only part of the picture (see 'man glob' for details for the rest of the story on wildcard pattern matching). This is sufficient for what is needed for these scripts. Using more complicated searching, such as with the square brackets ( [ ] ), curly braces ( { } ), and others used in globbing, will not work as expected as the rules are different than how they are applied in regular expressions (used by the 'egrep' command). I suppose I could do more substitution to make it closer to globbing, but I really don't see the need to do so at this time. NOTE: If your familiar with the extended regexp syntax, you could probably do more complicated searches with these scripts, if you remember to take into account the substition of * for .*, ? for .?, and . for \. ............ NOTE: Any changes or updates in code will be reflected here and explained in a following post below...........In other words, the code for these three scripts will always have the most recent changes in this post with an explanation in another post below. lspkg This command simply lists the packages currently installed on your machine. UPDATE: See post #53 below for more info. Code:
#!/bin/sh pkginfo This command lists the package's name, size of the package, the package description, and a list of the files installed by the package. UPDATE: See post #53 below for more info. Code:
#!/bin/sh whichpkg Ever wonder which package a file came from? That's the purpose of this command, to find the package a file comes from. UPDATE: See post #53 below for more info. Code:
#!/bin/sh I hope you find these as useful as I have. While you can get the same information using a graphical package manager, they are much quicker to use from the command line. Enjoy :) ---thegeekster |
You rock, sir.
I especially like lspkg. Nice and handy. Thank you very, very much. |
Thanx :)
But I did notice one little item in the code for whichpkg...............I forgot to add the -i switch in the grep command. It's this switch that makes the search case insensitive...............................LOL...which means I've been using it all this time as a case sensitive search...... :eek: I've already made the changes in the code above..............................but for those who may have copied it already, at the bottom of the code for 'whichpkg' change the two grep lines to read "grep -i ..." (simply insert -i after the word grep)........ |
*** lspkg UPDATE ***
NOTE: This update is superseded by the changes posted here..... :)
|
Thanks, been using these scripts since you first posted them. :)
|
I don't think I've ever posted one of my scripts before. I figure mine suck. As far as this, I've just been using this thing I wrote called 'sp' (Slack packages).
Code:
script=`basename $0` But how every Slack user doesn't come up with *something*, I dunno. It's too common an activity and pkgtool is just too slow. ;) Good stuff, thegeekster. Oh, and my less is 'export LESS="-eFMRXj12"' - using the default less the way I do might be kind of annoying. Oh, and alias cdp='cd /var/log/packages' is essential for manual inspection. Due to filenames, typing 'cd /v<tab>log/p<tab>' sucks. |
Hey, digiot, don't sell yourself short..................this is what open source is about, posting what you have for the benefit of others and if someone knows of a better or more efficient way of doing it, or spots a bug, then it gets fixed...........in other words, community involvement...............I'm sure mine can be improved upon, too.........
This is also why I post these scripts, making it useful for others and hoping others will come forward and help contribute their bit to the community.............and this allows users to have more choices, instead of limiting choices........... ;) I see your code is basically what I have, but all in one program, with one added ability..................I thought of making it all one script, but then I decided to follow the Unix programming philosophy of making a program do just one thing, and do it well.... :) I must say, I never thought of using the manifest file for searching if a file is part of the distribution as a whole, whether the pkg is installed or not...................gives me an idea of updating the 'whichpkg' script to first search locally for installed programs, and if not found, then search the manifest to see if it's even part of the Slackware distribution..................otherwise, it must be a third-party app and not officially part of Slackware.......... :) Also, you might be interested in knowing that you can 'cat' a zipped file (reading the file to the screen), whether compressed with gzip or bzip2, since they only compress a single file. The regular zip utility doesn't do this AFAIK, probably due to the fact it is not limited to compressing only a single file...................In other words, instead of unzipping the manifest file, just 'cat' the file in it's compressed form...............this way, you can save some disk space and still be able to read the file and pipe it through grep to filter the output The commands for these formats is zcat filename.gz for gzipped files and bzcat filename.bz2 for bzip2 files.......this will output the contents of the compressed file to the screen........so for your 'all' variable and '-a' switch you can do something like this: Code:
all=/home/j/var/MANIFEST.bz2 And anyone else.................feel free to step in and post someting you may have come up with..............if you know of a useful timesaver, then post it.... :) |
Quote:
/home/j/var/manifest lines 21792-21811/217164 8% instead of lines 1-22 (or whatever) in the status line which I figure might be useful for something. And with disk sizes these days I don't compress much. I second that, though - I look forward to more folks' posts. :) (OT - anyone else feel claustrophobic. ;) ) |
Quote:
Code:
all=/home/j/var/MANIFEST.bz2 And I'm not that familiar with the 'less' command, other than piping something to less.................so I learned something new and gives me something to play around with...... :) |
:o
Yeah. lesspipe.sh. I forgot that. :( Well, if you're not familiar with less, check out the man page - it's a great tool that can be a lot more effective than I think a lot of people realize. I obviously need to go read it again myself ;) (Still like 'em uncompressed, though.) |
*** chngcd ***
Here's a handy little script for changing CDs easily..................This is especially useful for you gamers whom oftentimes have to change a CD during gameplay........
To use, it's quite simple - open a console terminal and enter chngcd..........The CDROM tray will pop out automatically..........Then place a CD in the tray -OR- replace the current CD to continue -OR- remove the CD to quit, and then press Enter................You don't even have to close the CD tray, it will do it automaticallly................Simple and effective... ;) To make it easy to create the script, just copy-n-paste _all_ of the following code at once into a console terminal, and the script will be created automatically, not to mention being executable as well.......... :) If you prefer to do it the harder way, such as using a text editor, then copy-n-paste everything _except_ the first and last lines into the text editor...........Do not copy the lines containing __EOF__ NOTE: If you need to change the path to the CDROM mount point for any reason, after creating the script just open it up and change the CDROM variable to the desired path.......... Code:
cat << "__EOF__" > /usr/local/bin/chngcd && chmod 755 /usr/local/bin/chngcd |
Since a few bash scripters are gathered here, I'll ask here.
How can parse root=/dev/????? out of /proc/cmdline? |
Quote:
Code:
cat /proc/cmdline | grep 'root=' | cut -d' ' -f3 |
It has to be more explicit to handle any cmdline order.
I've been greping the small 't' and then '='. This works as long as there is no other small t, for instance in the kernel name. I thought sed might help but I don't know how to use it. using grep -d '=' also gets confused. can sed use a multi character delimiter like 'root=' ? |
Hmmm...........then see if this is what you want:
Quote:
|
Yeah great! i just add |cut -f2 -d '=' to that and it gets me what I want.
Does -z do like -v except it eliminates all FIELDS that don't match, or ?? |
-z is for testing empty strings.................in this case, the test is for NOT an empty string [ ! -z ... ], and by using the 'for' statement, it breaks up the input from the 'cat' command whenever 'for' parses any whitespace (blank spaces, tabs) or newlines, thereby letting you test each space-delimited field separately.......... :)
|
Re: *** chngcd ***
Quote:
/usr/local/bin/cdrom: ### beginning ### case "$1" in 'mount') sudo /sbin/mount /mnt/cdrom/ ;; 'umount') sudo /sbin/umount /mnt/cdrom/ ;; *) echo "Usage $0 mount|umount" ;; esac ### end ### And following in my /etc/sudoers ##begin## ivanatora ALL=NOPASSWD: /sbin/mount /mnt/cdrom/,/sbin/umount /mnt/cdrom/ ##end## Of course 'ivanatora' is my username, so if you want this to work you should change this. It can be easily modified to eject the cdrom, but I can't see the point. |
Re: Re: *** chngcd ***
Quote:
|
If anyone is having problems, there are two ways to overcome it....................either add the user to the same group as the block device ("disk" for Slackware), or change the permissions on the block device to make it readable for "others", ie., brw-r--r--
If you add the user to the same group as the block device for the CDROM, you might have to logout completely or reboot the machine............... :) |
thanks guys, those are really useful scripts.
|
Is there a page anywhere out there archiving all the useful bash scripts???
--Akshun J |
Quote:
Shell scripts on the web :) |
Nice. That will get my feet wet. Teaches me to come in at the end of a thread...
--Akshun J |
Here is a useful, if totally simplistic script, that is handy to see what Slackware packages in a given directory are *not* installed. For instance, I keep a local mirror of Slackware-current and I want to know if there are any packages in my slackware-current/slackware/gnome directory that are not already installed. I put a copy of this script in /usr/local/bin and change to /home/ftp/pub/slackware-current/slackware/gnome and run packcheck.sh. If anybody wants to improve on this, post your improvements here.
-------------------- #!/bin/sh for pack in $(ls *.tgz); do pack=$(basename $pack .tgz) if [ ! -f /var/log/packages/$pack ]; then echo "No Package $pack found" fi done ------------------ Chuck |
*** whichpkg UPDATE ***
NOTE: This update is superseded by the changes posted here..... :)
|
moving my post
|
I just wanted to say a big THANKS to you geekster! I've been using your scripts a bit and find them very useful :)
|
*** FINAL UPDATES for lspkg, whichpkg, and pkginfo ***
Okay, I think I've gone about as far as I can with these three scripts, lspkg, whichpkg, and pkginfo................They are all converted over from using regular expression syntax to wildcard matching (globbing). While not true globbing, they are close enough for practical purposes here...........If you're interested knowing what the difference is, read the manpages for globbing and regular expressions, 'man 7 glob' and 'man 7 regexp'. (Note - For KDE users, you can view the manpages in a html format by entering these urls in Konqueror, 'man:/glob(7)' and 'man:/regexp(7)'. This only works in Konqueror, not any other browser in KDE.).......Be sure to include the number 7 in both............
I did a major overhaul for the whichpkg script, making it easier to read the output, filtering out more of the unwanted garbage, and allowing for multiple search terms. It ended up being a bit of a challenge, more than I had anticipated....... :)..........but I think I've got it right (it sure did sharpen my regexp skills.......LOL).............A few search terms were quite unpredictable, most notably the searches for "ln", "file", "install" and "sh"...........If there are others you come across which seem not quite right, be sure to post them here and I'll fix it. otherwise this is pretty much the final update. The other two were mostly to convert to using wildcard searching (pkginfo) or a minor change in the usage of the wildcards in the search term (lspkg)..........Again, I don't see where they can go much farther, so these will also be the final updates. HOWEVER................I'm going to create another Slackware specific script to deal with orphaned files by looking at all the system files and matching them against the list of files found in the /var/log/packages/ and /var/log/scripts/ directories..............Then you will be presented with a report of all the files that aren't accounted for from the installed packages..............Some of these may be from various scripts and files you may have added manually, such as these scripts, but some may be leftovers from old installations no longer around.................Either way, you will have a list to look over and decide for yourself whether they belong there or not..............The reason for this script is from some of the posts I've seen recently asking about what files are safe to remove, or a way to determine which files are not wanted or needed...........I do love a challenge............. :D Okay, enought talk, the changes have already been made in the top post (post #1) above.... EDIT: Changed line number 53 in "pkginfo" script by removing the path "/var/log/packages/" (The third line from the end, above the two "esac" lines). Thanks goes to carboncopy for pointing out this error. :) EDIT2: More changes needed in the "pkginfo" script as noted below. |
Hi! I tested out all three new one but pkginfo seems to be not working properly for me. This is what happens:
Code:
bash-2.05b# ./pkginfo gnome |
Try changing the line:
cat /var/log/packages/$( echo "$list" | grep -i "$pkg" ) | less ;; to cat /var/log/packages$( echo "$list" | grep -i "$pkg" ) | less ;; |
carboncopy
Thanx for pointing out this error. gbonvehi has the right line that needs changing, which is line number 53 (the third from the last line, above the last two "esac" lines).................However, to correct it simply remove the path "/var/log/packages/" that follows the word "cat"...........it should read: cat $( echo "$list" | grep -i "$pkg" ) | less ;; OR you can use: cat `echo "$list" | grep -i "$pkg"` | less ;; NOTE: In bash scripting, both lines above are identical. The use of backquotes (not to be confused with the apostrophe) has the same meaning as using parenthesis with the dollar symbol in front of it.......I've changed my style to use the backquotes, ` ` , instead of the dollar sign/parentheses construction, $( ), because it's easier for me to type (On US keyboards, the backquote key is the one above the Tab key, to the left of the number 1 key)....... :D |
Okay, let's try this again.............for the "pkginfo" script, there needs to be another change.............I know what happened.........I changed the lookup from 'ls /var/log/packages/*' to "find /var/log./packages/* -prune -type f" which changed the output to include the full path....................
So _all_ the necessary change will be as follows (changes made according to the line number): Line 37 Code:
Change: Code:
Change: Code:
Change: |
Thanks for the Great Code. save a tonne of time (pkgtool --> view pkg).
|
OK, I haven't tried your new scripts yet (I will after finishing this post though :)), but I just wanted to say that if you can make the orphan script work I'd be very interested to see and use it. I tried to write exactly that kind of script but I must have given it too little thought 'cause it just was far too slow and memory consuming. In my script I also looked for "runaways", i.e. files belonging to an installed package that just weren't on the computer - perhaps something for your script too?
|
Bebo
It will probably take a bit of time to check the system files as it is, I don't really see any way around that, so I was only going to target the normal directories most apps install programs to...........And try to avoid any data directories or partitions.............I made a backup script a while back that is able to read /etc/fstab and /etc/mtab to find what system directories are mounted (such as /boot, /home /usr, etc.), mount the /boot directory if it isn't mounted {and unmount afterwards when done}...........And to exclude any mounted directories that are not the system directories (usually being the data directories)............ And yes, I was going to verify that what a program installed is still there........Basically, that would entail doing a check to see if the file exists by running through the lists of files in the /var/log/packages/ directory ( if [ -f FILE ] ; then ... ) and flagging the ones that are missing.............I was also going to use part of the code from my "whichpkg" script to verify the symlinks installed by programs as well................... :) And carboncopy........thanx for the vote of confidence..... :D |
I couldn't help myself, so I rewrote my orphans script from scratch. I hope you don't mind if I post it here. It's rather long, so pardon me for clogging this thread :)
Note: This script might still be subject to updates, which will then replace the script here in this very post together with update info in a new post. Info on most recent update is posted below. BEWARE: the script can of course NOT be used blindly - you HAVE to double-check the results! By this I mean that you have to make sure that the files reported aren't used/needed by some program. Although the script checks in both /var/adm/packages/* as well as /var/adm/scripts/* there will be false-positives, such as files generated by programs. These often contain important configuration, and other, data. For instance, some (most?) of the files in /etc that are reported as orphans might be extremely important. Anyways, here it is. Code:
#!/bin/sh |
Quote:
One question...........How long does it take to execute your script?......................I noticed that you pushed the script's priority way back to the minimum priority..............Myself, I would just use the ampersand to run the script in the background ( <scriptname> & ) If you want to time it to the nearest second, here's a little script, called "elapsed", I whipped up for just that purpose.............To time a script just add the variable START=`date +%s at the top, and at the bottom of the script add this line (assuming you save the "elapsed" script in /usr/local/bin): /usr/local/bin/elapsed $START `date +%s` . This will give you the elapsed time to the nearest second. Code:
#!/bin/bash Another thing is why not try to do the check on the fly, if you can.................it would save some time by not having to first create lists then having to read them.........As for the arrays, I haven't used arrays in bash scripting (yet) because I haven't found the need to.......*shrugs* To show you what I mean, here's a sneak preview of the script I'm creating. This is a function that checks for missing files (what you call renegades, I think) on-the-fly, using 'egrep' for the filtering..................I'm still working on this but it's functional as it is: Code:
#!/bin/sh |
Hello,
I've just updated my script posted above. Edit: Obsolete update info removed. thegeekster, The reason for renice'ing the script is just to stop it from taking all CPU. I don't want to ampersand it - or whatever the proper expression is - since I want to see that something is happening. Which of course also makes it slower; there are loads of echo'ing and tput'ing going on. Maybe I should give it a non-verbose option? As for the timing... [And here I've deleted a bunch of crap about the fastness of my script that I wrote but of which I have no idea whatsoever where it came from.] So case is faster than if? How come? BTW, if you want to calculate the elapsed time from seconds only, try date +%s :) Ah yes, I forgot. The reason to chop the directory tree in small pieces and search one bit at a time is not only to have something nice (well... :)) to look at. I also wanted the list to grep in to be as short as possible. It takes a very long time to do a grep AFILE -f ANOTHERFILE when the lists contain tens of thousands of words. Well, cheers :) |
Here's a second update to my script above. Main points:
(1) The use of arrays is resumed. It is actually faster to search through an array than a file - if the arrays aren't too large. If I put the package files in an array instead of a file, my script will be a lot slower. (2) The verbosity is decreased, since it gives worse performance when the info on the terminal is updated quickly. (3) The --quick option is gone. Turns out it wasn't so quick after all. Has to do with counting the number of elements in an array methinks. (4) New option: --prune. Only search in the given directory - do not descend in directories below. (5) The issue with /usr/bin/[ is fixed using the -F grep option. (6) Some logging is done, timing for instance. In nanoseconds. [Again, I have deleted some stuff about the script's fastness. What's the point of keeping track of the performance of an erroneous script?] This is fun :D |
Quote:
Anyway, I did another upgrade to the pkginfo script above to include any info from the installation script (doinst.sh) if one is found (not all packages have, or use, a "doinst.sh" installation script). This will be added at the bottom of the output to the screen, under the heading of "INSTALLATION FILE:" (just scroll down until you come to it)...............I thought this would be good to look at, too, for any additional information on what was done besides the adding of files from the package itself during the installation process (Remember the line that says Executing install script for <package_name>... when you install a package with the 'installpkg' command?)........... :) I also did some minor code changes to the "whichpkg" script as well. There are no added features, tho', so it's not absolutely necessary to upgrade it........ Enjoy :) PS: Read the section on PATTERN MATCHING in the original post above for important info on the "hybrid" pattern matching used by these scripts. |
Does one of you know the command to find a missing file in Manifest. i saw this once, but then couldn't find it. I've seen some suggestion using zless, but what I want is something like: gunzip Manifest.gz |grep "somestring" (maybe there was a 'cat' in there too), that works with it without leaving the file uncompressed.
|
Quote:
Code:
zcat |
Quote:
You can replace the less command with the grep command........... :) |
Yeh, that's a start, but I need it to get the package name too, in case the file has a name that's not part of the package name. perhaps by patching your whichpkg...
I haven't tried yours and bebos scripts yet, waiting till you both are satisfied. But finding the package name for a missing file from the Manifest seems to be the most accurate way to track a dependency for any standard Slackware package, at least. |
Okay............If I understand you correctly, you're looking for something that will give you a dependency check of sorts..............plug in a filename name and it'll tell you which Slackware package is needed........
However, this method won't work when plugging in a name of a symlink (or a renamed file) as the MANIFEST file gives you an exploded list of the files stored in each package, whether source or slackpack..........but slackpacks don't store the symlinks in the package, they create symlinks after installing the stored files using the doinst.sh script, as well as renaming files........... Basically, you would have to not only look at the filenames inside the packages, but read and analyze any doinst.sh scripts inside each package (if the package has one)..............and to do that, you would need to have a local mirror of the slackware tree....................it could probably be done using the first and second installation CDs.................Unless another list was created containing the symlinks and renamed files for every Slackware package............ Hmmm........this is beginning to sound interesting....... :) |
Okay, here's a quick and dirty solution for searching through the MANIFEST files to find the file you're looking for and the package it will be found in.......
First grab the MANIFEST.bz2 files from a Slack mirror..........for each Slack version there should be a MANIFEST file in the directories extra. pasture, patches, slackware, source, testing. (NOTE: The Slack-current tree won't have a patches directory.).........Then run the following command on whichever MANIFEST file you choose, replacing FILENAME with the file you're looking for: Code:
bzcat MANIFEST.bz2 | egrep '(Package:|\<FILENAME$)' | egrep -B1 '\<FILENAME$' For example, here's the ouput when searching bzip2 in the slackware-10.0/slackware/MANIFEST.bz2 file: Code:
$ bzcat MANIFEST.bz2 | egrep '(Package:|\<bzip2$)' | egrep -B1 '\<bzip2$' |
That seems interesting. I'll have to look at that tomorrow, though, as it's getting late here in Deutschland. Does that work if FILENAME$ is not part of the package name? Is that case sensitive or any other caveats?
maybe an 'incomplete' search (without looking in the doinstall.sh) would still be useful if the search string was general, since some/most symlinks have a similar name. However, an exhaustive search, seems like the only dependable way to resolve a dependency if it can be done with a Slackware package. |
Quote:
The search is for the filename, but how it works is the first 'egrep' command will list all the lines with the word "Package:" along with any lines that may include the search term (filename) you are looking for, listing each in the same order it finds it............while the second 'egrep' command will again look for the desired filename, but also include the line above it from the output of the first 'egrep' command, which _should_ be the name of the package....... Remember that the search is for any lines containing the search term at the end of each line, which will exlcude the names of packages..............It's the second 'egrep' command which will include any line above the matching line from the output of the first 'egrep' command, which will hopefully be the name of the package Quote:
|
The orphan/renegade search script is updated. It has taken some time to get this finished, mostly due to some bug-mud I fell in concerning the declare -a that for instance the Advanced Bash-Scripting Guide says should speed up the use of arrays. It does speed it up, but it also makes the arrays unable to contain elements with spaces and parenthesis and stuff. Pretty odd, I'd say. The script should be fairly ready for use by now, but it can of course not be used blindly - you have to check the results! There are mainly two classes of false-positive orphaned files: (1) files generated by other programs, often containing configuration, and other, data, and (2) files in /var. The /var directory should perhaps be completely excluded from the search. Also, /bin/bash is of course a false-positive, since it is renamed from the package name /bin/bash2. Other possible false-positives are the man pages, since they sometimes are gzipped, sometimes not. On my system they do not show in a search, though, so it seems ok.
The most important update is the search for orphaned directories. This will first locate the directories on the file system that are not explicitly seen in /var/adm/packages/*. The created list of orphaned directories is collapsed to be as short as possible. The search for orphaned files is then adapted to exclude the orphaned directories. This means that the orphaned files in an orphaned directory will not be listed since they are included in the orphaned dir. This gives a performance penalty by a factor of about 2 compared to the former version, but it is a nice feature that I didn't want to leave out. It searches the 4 gigs of system files (/usr /bin /sbin /opt/kde and so on) on my computer in 10 minutes which is still bareable. If you look carefully at the code, you might object (to a lot of things, but perhaps the thing I'm after here) that it should loop over the contents in $PACKAGEDIRS instead of $(grep -xf "$PACKAGEDIRS" "$DIRTREE") in the search for orphaned files. However, then it will follow symlinks, and in some cases erroneously classify the files seen under the symlinked directories as orphans. There is also a new --quiet option which will disable the logfile. It could also be disabled by just setting LOGFILE="". Now to something completely different. You know all those .new files that you find in for instance /etc after an update? It can be quite boring to locate all these and rename them, so I whipped up a script (oh, really? :)) to help me in this. It also backs up the older scripts, appending a .old, up to a maximum of two old versions. Here it is: Code:
#!/bin/sh |
All times are GMT -5. The time now is 03:13 PM. |