Mar 28, 2013

Getting hold of a remote PID through Paramiko

By means of this article, I would like to share with you a little trick so as to obtain the PID of a remote process run through Paramiko. That is, figure for a moment that you launch an application on a remote system by using Paramiko, and you would like to kill that process after a certain timeout.

To be able to do that, you will have to grab the PID of that process after running it, and if you do not want to use "grep" or other kind of filters like this, the shell provides a curious mechanism which consists in executing that process in a new shell and afterwards, reading the PID of that process which has just been run.

Let's see an example.

import paramiko

if __name__ == "__main__":
    
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect("ubuntu-server.local", username="javi", password="xxxxxx")
    
    _, stdout, _ = ssh.exec_command("echo $$ ; exec python test.py")
    pid = stdout.readline()
    print "PID of the remote process: " + pid
    
    _, stdout, _ = ssh.exec_command("ps -eo pid,command | grep %s" % pid)
    print "Looking for the process:\n" + stdout.read()
    
    ssh.exec_command("kill -s SIGINT %s" % pid)
    ssh.close()


As you can see above, I am running on a remote server a straightforward script called test.py with the following lines.

while True:
    pass


Before executing the script through exec (replaces the current process image with a new one), I have put the order "echo $$", and in this way, I will be able to dump the PID of that process. Finally, I am using that PID to search for that process by means of ps and kill it. Let's run the module.

$ python remote_pid.py 
PID of the remote process: 6020

Looking for the process:
 6020 python test.py
 6021 bash -c ps -eo pid,command | grep 6020 
 6023 grep 6020


Mar 17, 2013

Setting up a CVS server on Ubuntu

Installing a local CVS server can be really useful although you do not have huge information to control or many people working on the same project. You can just want to have controlled all your documents. For this case and many others, you can quickly set up a version controller such as CVS.

So let's get started by installing the CVS client and server (Ubuntu Server 12.10). During the installation, you have to choose a name for your repository (or repositories). In my case I went with "myrepos".

$ sudo aptitude install cvs cvsd


Then you have to initialize the repository and change the directory where CVS lock files will be dropped off (instead of directly in the repository by default). Remember to create that new directory.

$ sudo cvs -d /var/lib/cvsd/myrepos init

$ sudo vim /var/lib/cvsd/myrepos/CVSROOT/config
...
LockDir=/tmp/myrepos

$ sudo mkdir /var/lib/cvsd/tmp/myrepos


Now you only have to create an user for the repository and modify its owner.

$ sudo cvsd-passwd /var/lib/cvsd/myrepos javi
/usr/sbin/cvsd-passwd: adding user 'javi' to '/var/lib/cvsd/myrepos/CVSROOT/passwd'

$ sudo chown -R cvsd:cvsd /var/lib/cvsd


Let's restart the server and check it out from the localhost.

$ sudo /etc/init.d/cvsd restart

$ sudo cvs -d :pserver:javi@localhost:/myrepos login
Logging in to :pserver:javi@localhost:2401/myrepos
CVS password: 


Mar 2, 2013

Speeding up Python with Cython (III)

Let's carry on with the last article about speeding up Python with Cython. After running the test.py script again by using now the new version of the module, we obtain as follows.

cython$ python test.py 
0.0394711971283


Now the improvement achieves the 98% apropos of the first round. Let's take a look at the new HTML file in order to discern which parts of the code have been directly turned into pure C code.



From the previous picture, it can be asserted that apart from the two static types, a couple of critical structures have been also translated into C: the loops. Cython also provides another C-style syntax so as to write loops. The following file uses this kind of structure, but remember that will not produce any improvement because those loops have already been translated into C.


def calculate_primes(int limit):
    primes = []
    cdef int number = 0
    cdef int divisor = 0

    for number from 2 <= number <= limit:
        for divisor from 2 <= divisor <= number:
            if number % divisor == 0 and number == divisor:
                primes.append(number)
                break
            elif number % divisor == 0 and number != divisor:
                break

    return primes


You can check the documentation located on the Cython website and learn lots of code structures provided by Cython. For example, if this method was embedded in the main script (not as an imported module), you might develop the next optimized method, where the function returns a pointer to an array, and that array has been defined as static and not as a Python list.


cdef int *calculate_primes(int limit):
    cdef int primes[10000]
    cdef int number = 0
    cdef int divisor = 0
    cdef int i = 0

    for number from 2 <= number <= limit:
        for divisor from 2 <= divisor <= number:
            if number % divisor == 0 and number == divisor:
                primes[i] = number
                i += 1
                break
            elif number % divisor == 0 and number != divisor:
                break

    return primes


Let's test out again the HTML file generated for this method.