Showing posts with label shell. Show all posts
Showing posts with label shell. Show all posts

13 March 2008

get absolute path from relative path

I think this is a quite common issue, but googling for it doesn't (easily) get the very useful solution I finally found. So I put it here.
The solution is really easy and it's called readlink.
Given a relative path like../symLink/myDir, simply type
readlink -f ../symLink/myDir
and you will get something similar to
/root/path/to/symLinkTarget/myDir
Of course you can also get the full path for a file instead of a directory (myDir → myFile.ext still works). The only point, as it is understood in my example, is that symbolic links are followed, so you cannot get the "symbolic" path to your dir/file. But this could be view as a feature. Suppose you want to know the full real path of your sym-link-reached working directory, you can define a very simple modified pwd command alias like this
alias Pwd='readlink -f .'
and compare its output with the usual pwd output.
Enjoy!

23 April 2007

remove first lines from a file

head shows the first N lines of a file
tail shows the last N lines of a file.
But what if you want to remove the first N lines of a file? Simply show the last lines of the file startin' from the N+1 line! Ok, the point is that tail has an option like this: simply give the line number to start from just after the plus sign. Exempli gratia:
tail +12 too_much_header_lines.out > just_lines_I_want.out

14 March 2007

get environment variables of a process with ps

Have you ever heard of the e option of ps? As man says, it shows the environment after the command. Used in conjunction with the twice wide-output option, ww, it gets ps to swamp the screen with the whole information about the environment setup at the moment each process was launched. Try it yourself, for example:
ps eww | tail -1
As the tail -1 says, the huge mess you get is a single line of output, corresponding to a single process (most likely it is just the last tail process itself...). If you take a look at that mess, you can see that it is a long list of pairs VAR=value, and it actually represents, as said, a snapshot of the environment at the moment the process started. For example you can find SHELL=/bin/bash or USER=hronir, or HOME=/home/hronir and so on.
Yeah, all this information is too much, but there are situation where one or few of those info could be valuable. Imagine, for example, that you are launching the same script from different directories (for example in order to analyze different set of data, placed in those different directories). Then, maybe after some period, you poor find out that some of these scripts, for any reason, failed to get done. For example you check with top or ps, grepping for your script, an it turns out that there are less scripts running than you launched. The big question, now, is: which script is died, and which not? Which data are still under analysis and which need to be re-submitted? (Your analysis take a lot of time, and you hope to find a way not to resubmit all the scripts...!)
Well, the answer for all these questions is just in the eww options of ps. And in particular in the PWD=/full/path/ pair, which will tell you where was the still running script launched from.
The point, now, is to make it easy to read out the value of this pair among the many others, since a huge number of screen-lines for each ps-output line is very very cumbersome to handle.
Well, after a full afternoon struggling with sed, awk and regex, I came out with this very poor result. Take your ps call grepping your scripts
ps -ely --forest | grep myscript.pl
make sure to add the eww options:
ps -ely --forest eww | grep myscript.pl
and pipe its output to sed as follows:
ps -ely --forest | grep myscript.pl | sed -r 's/(.* )? ([A-Z|_]+)=.* (PWD=\S* ).*/\1 \3/ ' | grep --color=auto PWD
It would be too boring and pedantic to explain the full path to that regular expression pattern. Let me notice only a few things.
First of all, I still not understand the behavior of this regex pattern, in particular the (.* )? (which is supposed to be related to the greedy expressions, but I think to well understand this concept and not the particular behavior I find in this case) and and some fair variations I tried...
Moreover, most of the time I wasted was spent trying to get a parametric version of this solution. A way, I mean, of asking to take out any of the pairs ps eww streams out. Actually I tryed to make a (ba)sh script (function), a perl script... but I didn't find the way to make something very svelte to be used beside the ps command. The utmost I get is to define an alias like this:
alias selectPWD="sed -r 's/(.* )? ([A-Z|_]+)=.* (PWD=\S* ).*/\1 \3/ ' | grep --color=auto PWD"
to be used as follows:
ps -ely --forest | grep myscript.pl | selectPWD
From this, of course, I could easily get any selectXXX I would need, but... can you find a parametric solution?!?
 
PS
Have you ever heard of the --color option for grep? Long ago I set alias grep='grep --color=auto' in my .bashrc...