Tag Archives: bash

how to: using lftp to mirror an ftp site

I encountered this problem before and back then, I tried to solve it… and I did, using wget. I totally forgot about this until it came back to haunt me… hahahaha!

Back then, I used wget with the -c option, means to continue/resume a partially downloaded file, or skip if the file is already downloaded. Note that it’s using the file size as basis… This can lead to a disaster if the file on the receiving end has the same file size but with a different content…

And so my quest to find a better solution begins… (again!)

Anyway, I stumbled on this command, lftp, which has a good mirroring support. And so, after a quick read, I came up with this script:


#!/bin/bash

dir_log="$HOME/log/$(date +%y%m)"

mkdir -p $dir_log

deb_file="$dir_log/$(date +%y%m%d).mirror.log"

lftp << EOC
debug -o $deb_file
open your.ftp.site.here
user ftp_user ftp_password
mirror -e dir_to_mirror "$HOME/mirror_dir"
quit
EOC

And so, just another bash script… hopefully, this one won’t haunt me 🙂

Advertisements

how to: using bash to kill a parent process and all spawned child processes

I got this project in a Linux environment where I have to terminate a process before running one. Sounds easy at first glance, it’s very easy to kill a process in Linux, all I have to do is get the process’ PID (process id) and terminate it using the kill command…. HA! A no-brainer problem!

But after thinking about it for a few minutes, it hit me, it’s possible that the process that I want to terminate can spawn child processes, and it’s child processes can spawn another set of child processes… and so on… and so forth… and I have to terminate all these child processes too! Aaarrggh!

And so, all because I’m lazy, I opened up Google and did a little script hunting. I found some tips but it doesn’t fit my needs. Most solutions were how to kill one level of child processes only (or maybe I did not try hard enough). After a few hours wasted on looking for a “already-done-by-others” solution, I gave up and decided to write my own….

So much for being lazy… So, on to the drawing board…
Well, I hope you can make sense of what’s the diagram above (don’t ask me how I came up with it…). If you don’t know what it is, just believe me when I say it’s a tree.

The behaviour of a process spawning child processes can be described by a tree. Based on this, all we have to do is determine the nodes at each depth. The idea is to store process ids in an array based on what depth in the process tree they belong. After generating the array, we can decide if we want to terminate processes from parent to child or vice versa. In my case, I have to terminate from parent to child.

Based on that gibberish idea above, I managed to write the following code:

#!/bin/bash

ids[0]="$1"

index=0
quit=0

while [ $quit -eq 0 ]
do
    ((index++))

    # get all child processes spawned by this/these ppid/s
    ids[$index]=$(ps -o pid --ppid ${ids[$index-1]} | \
      pcregrep '\d+' | tr \\n ' ')

    # if no child processes found
    if [ ! "${ids[$index]}" ]
    then
        # quit
        ((quit++))
    fi
done

# kill process from parent to all child processes
for i in $(seq 0 ${#ids[@]})
do
    if [ "${ids[$i]}" ]
    then
        kill ${ids[$i]}
    fi
done

The code above assumes that the root process id is known. You may have to do some checking first if you have a valid root process id as parameter.

And that’s it! I’m just hoping that my laziness can appreciate fruition…