Passwordless scp with Python and pexpect
Posted by rahulsinner in Python on Thursday, March 18, 2010
I have to deal with a lot of Unix/Linux/BSD boxes at work. The problem with such large number of boxes is copying my config files and .ssh directory first time I use them. Many a times, for some new work, I need to configure multiple boxes. It's quite a pain to enter passwords and pass-phrases that many times.
So, I decided to automate this copying with python and pexpect.
The script is really simple. You invoke it as follows:
$ pyscp.py -s .ssh,.vimrc,.zshrc,.screenrc,.inputrc -t node1,node2,node3
It will copy .vimrc, .zshrc .. to mentioned nodes. The automation looks for prompts asking for passphrases or passwords. You just have to enter your passwords once. On all subsequent attempts, the cached passwords is reused.
Password-less access can be configured using ssh-agents as well but this approach is generalized for all the cases - ssh not configured for public key authentication, ssh configured for keys with/without passphrase, with/without agent.The code can be cleaned further and made more elegant but it does the job.
The beauty of node.js (Follow-up)
In the last post, I presented a simple port forwarding solution using node.js. The solution was simple, elegant and scalable. I got a follow up from Jeremy Ashkenas presenting a solution in Coffee Script.
I have a personal preference for terse syntax, one of my reasons for liking Python and Clojure.
For a little background, the coffee script compiler translates the given program to javascript and then it would run on any platform where Javascript runs. I queried him about how long and how extensively he intends to support Coffee Script. I am copying his response verbatim.
"I would say that it's not very mature yet. Aspects of the language syntax have changed as recently as last week. That said, CoffeeScript compiles into vanilla JavaScript -- it's not a runtime, and it's not a binary compiler, so even if the language were to go away tomorrow, you'd still be left with a bunch of completely usable JavaScript.So while I'm not using it for any real-world projects, other people are, and I'm not too worried about their future viability. In the absolute worst case, they can always used the output JS, which is pretty-printed, with comments inline."
The beauty of node.js
At work I came across a problem which needed ack remote file copying complete event. Most of the data comes on ftp and when the data arrives, some processing has to be done on it. The problem is to when to kick in the processing. If we do a cronjob approach, the cronjob processor can't know for sure if the new file has been pushed completely. inotify posix system call only tell you the status of the file viz. created, modified, read etc.
EDIT: inotify does allow you to listen for the write complete events. The flag to look for is IN_CLOSE_WRITE. I kinda missed this.
The fix we have at work is to change the ftpd itself. The ftpd writes to a unix named pipe when the transfer completer. The listener daemon is watching the named pipe for changes and kicks in the callback when a new entry is made.
This works but has a couple of issues.
- Changing the ftp daemon itself means keeping up with the ftpd changes. If a new release of ftpd is to be deployed, the patch has to be applied.
- The same patching needs to be done if we decide to support another service. If we decide to allow rsync, similar fix has to be done for rsync as well.
How we do at work isn't going to change because our push data is solely ftp. But given a chance to re-design it, I would simply write a port forwarding service. The port forwarding server would listen at a dummy ftp port incoming. When a connection is made to port incoming, it would open a client connection to real ftp server. It would forward the whole traffic and it's only job would be to trigger the callback when the ftp transfer completes.
This solution required writing some code. Out of box port forwarding solutions don't have the customization for listening to end of transfer. So, faced with a problem, I did what everyone does - googled it. I found two acceptable solutions in Python. I prefer to code much of my stuff in Python for some obvious and not-so-obvious reasons(coming soon - topic for some other inflammatory post).
One of the solutions was spawning threads:
Port forwarding using threads
And the other one was using asyncore module.
Port forwarding using asyncore
The solutions worked and looked good for my taste. But something seemed amiss. It looked like just too much work when all I want to do is to know when the communication completes. I looked around a while and coded this in node.js.
The solution works and is terse, concise and highly scalable(look at the node.js website for how and why). And above all, it's as simple as it gets.
The code itself is pretty simple. I create a server and install callbacks for it. On connect event, I create the client for real service. Client and servers listen for receive, and the callbacks just sends data from one socket to other. The server socket triggers the callback on receiving the eof.
For the example, I am forwarding port 7000 to port 22. When we run the code and do a ssh on port 7000, the traffic is correctly forwarded to sshd running on port 22.
node portfwd.js
ssh -p 7000 localhost
This solution can be extended(must be extended) to function as a fully fledged port forwarder. The configurations(which port to forward where) can be passed as JSON. And the services to which we are forwarding should be made inaccessible to the outer world. For example, sshd can be configured to listen only to loopback address. This is important otherwise we run the risk of circumventing port forwarding and not running the callback.
There is much that can be done in node.js. This is just the tip of the iceberg. Looks like Javascript is really on the rise.
Sharing code with github
Posted by rahulsinner in gists github on Saturday, February 6, 2010
I have been using pastebin to share code for a long time. While reading through a couple of blogs, I saw that github gists allow to share code in a prettier manner.
{-7, 1, 5, 2, -4, 3, 0}Objects: Functional programming style
Posted by rahulsinner in closure perl "functional programming" on Monday, December 7, 2009
Functional languages which don't have build in objects support can implement object oriented programming using closures. Closures help implement encapsulation and the inheritance can be achieved using composition. The members can be maintained as members in hash ref. The hash ref will be closed by a closure so that external modification can't be done directly on it. Here is a sample code implementing encapsulation, inheritance and polymorphism.
Employee class extends person. It uses composition to implement inheritance.
The dispatch subroutine is the helper for implementing inheritance and polymorphism. You can see that this trivial code implements many important OOP concepts.
K&R - timeless classic
Posted by rahulsinner in c programming on Tuesday, November 17, 2009
There is a recent(well, may be not too recent) trend geared towards becoming overnight programmers. Peter Norvig has commented about that.
Viewing a couple of discussions on the web, I see people saying that K&R is hard to follow and they would prefer something with more examples and elaborations. I would drop any iota of diplomacy here and would say if you can't follow K&R, you are hopeless and either continue to be a monkey coder or find an alternate career.
K&R is the ultimate example of concise, complete, practical technical writing. I believe it is one of the primary reasons behind C's popularity. Everytime I re-read the book, I learn something new. And I am not the only one who feels that way. The coverage is comprehensive and explanations are lucid. The specs at the back used to be the standard C specs for the first 10 years or so. The examples are real world complete programs. Exercises force you to stretch your mental abilities. Compared to it, the other C texts look like a joke(with a couple of exceptions).
I am seeing a rise in head-first series now-a-days. I have read a couple of them and I did find "Head First Java" enjoyable. But again, it's suited only to the beginners and someone with some programming experience won't be too happy with it.
K&R is something I am religious about and would protect it to death. If you believe I am being over zealous here, read the book cover to cover and try the exercises. If it doesn't give you a better understanding of C and programming as a whole, you really don't have the aptitude for programming.
Standard *nix utilities using Perl
Posted by rahulsinner in perl "linux utilities" sed grep awk on Sunday, August 9, 2009
Lately, I have been working on Perl and though I am not a big fan of the language, it does come handy for a variety of tasks. One of the reasons I like to keep in touch with Perl is it can very easily be used as substitutes for various *nix utilities viz. grep, sed, awk, find etc.
But why would someone want to do that when you already have the standard utilities? Well, you might be used to do everything in Perl. Or you might be on windows where the shell utilities are either non-existing or leave much to be desired. MS does claim to change that with PowerShell but I haven't looked at it yet.
So, enough talk. Here goes my short list of handy Perl one liners.
1) grep
grep is one handy little utility which does a full text search on the specified files.
$ grep -n 'main' *.c
formatting.c:3:int main(void)
hello.c:4:int main(void)
It can be done with a Perl one liner by using regex.
$ perl -ne 'print "$ARGV: $.: $_" if /main/; close ARGV if eof;' *.c
formatting.c: 3: int main(void)
hello.c: 4: int main(void)
2) sed
'sed', the venerated stream editor, is mainly used for substitutions.
$ echo "Hello world" | sed -e 's/Hello/Hi/'
Hi world
The perl equivalent for the above would be:
$ echo "Hello world" | perl -pe 's#Hello#Hi#'
Hi world
Neat, huh!
3) awk
awk is generally used for parsing delimited input. This is what we would do to get the username field from /etc/passwd.
awk -F: '{print $1;}' /etc/passwd
The perl one liner for this one would be:
perl -F: -lane 'print $F[0];' /etc/passwd
4) find
find is trickiest of them all. There isn't a shortcut available for it. Though the standard module File::Find comes handy.
To find and print all "*.c" files under directory "/usr/src", the find command would be:
find /usr/src -name '*.c' -print
The Perl equivalent is:
$ perl -MFile::Find -e 'find(sub {print "$File::Find::name\n" if /\.c$/;}, "/usr/src")'
There are other utilities which can be done using Perl viz. sort, cut etc. But these 4 are the ones that I miss the most when I am not on *nix.