Sunday, August 01, 2010

» Shell trick: CRLF to LF

I do this again and again in RPM .spec files, so just in case: a little trick to remove the CR from CRLF ;) (Windows uses two bytes for end-of-line markers, namely CR and LF, while Linux and Unix only use one: LF) You might of course use dos2unix or recode, but this one works in-place, which means that you don't need to make a copy, work on the copy and then copy (heh) that file back onto the original -- here is how to do it with dos2unix:
cp file file.orig && dos2unix file
And here the shorter version, using sed and its in-place editing feature:
sed -i 's/\r$//' file
Might as well do it with Perl, which also supports in-place editing:
perl -pi 's/\r$//' file
Update: as _Marcus_ just told me, recode actually does in-place editing by default, my bad :)

Labels: , , , ,

Saturday, June 26, 2010

» Finding out whether a script is piped

When writing shell scripts, sometimes you need to find out whether your script is being piped into something else (e.g. a pager like less, or just running on the terminal (unpiped). One use case could be to determine whether you want to enable ANSI style colouring of the output or not. Turns out it is really simple to do.

Shell

To do that from a bash script, use [ -t 0 ], which is true when unpiped, and false when piped:
[ -t 0 ] && COLOR=1 || COLOR=0

Perl, others

In other scripting languages (or even in C/C++), where the isatty function is available, use that -- this example being in Perl:
use POSIX 'isatty';
my $color = isatty(STDOUT);

Labels: ,

Saturday, July 19, 2008

» Reattaching to ssh-agent

A rather rare situation, hopefully... I happened to clean up /tmp and delete a temporary directory used by ssh-agent, that held the UNIX domain socket that was used to communicate with it. Arguably, that's a pretty stupid thing to do and fixing it is as simple as logging out (of your X session) and in again. But I didn't want to close running applications and hence, hacked a little bash function to re-attach to a running ssh-agent (which means setting the environment variables SSH_AGENT_PID and SSH_AUTH_SOCK appriopriately) after having started another ssh-agent process. As it might be useful to others (or just an interesting sample of bash scripting), here it is:
function reattach-ssh-agent {
   local pid
   local line
   local r=$(ps h -o pid -C ssh-agent | while read pid; do
      sudo lsof -a -w -LPn -p "$pid" -U -Fn \
      | grep '^n/tmp/ssh-.*/agent\..*' | while read line; do
         line=${line#?}
         [ -e "$line" ] && {
            echo "FOUND: pid=$pid sock=$line" >/dev/tty;
            echo "export SSH_AGENT_PID=$pid; export export SSH_AUTH_SOCK=\"$line\"";
         }
      done;
   done)
   [ -n "$r" ] && { eval $r; } \
   || { echo "Failed to find running and operational ssh-agent" >&2; }
}
Note that it must be a function, not a script as the latter would be executed as a sub-process of the current shell and, hence, not be able to modify the environment of the current shell (which is the whole idea about it). So if you need that function here and then, make sure to add it to ~/.bashrc Also note that a major drawback of this function is that it requires executing lsof as root (here using sudo) as the open files of ssh-agent are only visible to root. Another approach would be to implement the above in a separate script that would just output the shell code to execute (export SSH_AGENT_PID ...) and run setuid (using a C wrapper or such) but.. not necessarily easier nor much more secure.

Labels: , ,