Creating a (low) fat Client environment for LTSP

For more detailed instructions please look here: http://www.nubae.com/ltsp-linux-terminal-server-project-netbooted-fat-client-for-ubuntu-hardy-and-intrepid

LTSP stands for the Linux Terminal Server Project and is about the coolest and most cost effective technology out there. I've been fortunate and privileged enough to be working with this technology in schools and businesses. Generally LTSP reuses older hardware that runs as a terminal connected to a powerful server. In this way, older penitum and pentium 2 machines can run at practically the same speed as the server feeding them. This is because the processor and ram of the server are actually being used, with only the screen, keyboard and mouse being used on the terminal end. This is great for older machines and dedicated thin clients (which can cost as little as 50 euros), but for newer intel core 2 duo machines, running them as thin clients would be a waste. That said, the benefits of having a centralised location for the computer image and management of users is extremely helpful to an Administrator. This is where a low fat netbooted client comes in. Instead of running the programs on the server, the entire environment is run in the client, hence the term fat. This also relieves the server cpu and ram, as well as the bandwidth of the network slightly, and is ideal for multimedia systems that require Flash, Video, and Audio streaming. Installing the fat client is very easy and requires you downloading the script from here for Ubuntu Intrepid Ibex.

/usr/share/ltsp/plugins/ltsp-build-client/Ubuntu/030-fatclient

You then build your fat client by doing:

ltsp-build-client --chroot (name-of-chroot) --fatclient Ubuntu --highfat

Not the capital U in Ubuntu. The usage of --highfat is an extra option that builds a full multimedia sytstem and is quite resource intensive. A normal fat client has only the base educational games and programs, along with a basic internet suite. The --chroot (name-of-chroot) option is not required, it is only used if you already have a thin client environment under the default i386, which is under /opt/ltsp/i386, so name-of-chroot here would be something like fati386, which would correspond to the location /opt/ltsp/fati386/.

You can see an image here of the thin client in action:

Rate It! (Average 4.00, 1 votes)



eggdrop IRC bot with logging to website

After playing around a bit with the php bot logging to mysql, I turned to a little more industrial solution, which involved installing an eggdrop bot and a script which lives inside the bot to convert its log files to html. This turned out to be the easiest solution, albeit a time consuming one. First it was necessary to install an eggdrop bot, which on Debian and Ubuntu can be done like so:

apt-get install eggdrop

This installs the eggdrop to its global area, and if like me you want to run it from a specific user's home you need to copy the configuration file (eggdrop.conf) to the home dir of your choice (example: /home/logbotuser/eggdrop.conf) You must thoroughly go through the configuration file, and uncomment various locations that stop you from executing the bot without reading through ALL the configuration options. The important stuff is at the top, like the botnick, the channel, etc, but there is also important stuff further down, like which irc servers to connect to and the like. When you are done, you should start the bot doing:

eggdrop -m eggdrop.conf

you use the -m option only the first time, as this tells it to create a new user list, after which you can msg the bot hello from irc, or telnet into it and type NEW as the username. The bot should now be happily running on the channel of your choice. One other thing you can do is setup a cron job that makes sure your bot is running always. Basically the crontab checks every 10 minutes to see that the bot is still active, if it isn't it relaunches it. To set it up, move the botchk script from /usr/share/eggdrop/scripts/ to your user directory:

mv /usr/share/eggdrop/scripts/botchk /home/user/eggdrop/

Then you need to edit the bothck script which has some self explanatory settings corresponding to what you already configured in eggdrop.conf, but something that is not mentioned is the need to replace the 3 entries that have the string ./ $botdir to:

/path/to/eggdrop/dir/ $botdir

In the example above that would be /home/username/eggdrop/ $botdir

You then need to do the final part which is add the crontab entry like so:

crontab -e

Here you add the following line:

0,10,20,30,40,50 * * * *   /path/to/botchk

Now you can now download the logs2html script from here.

To install it, unzip it and follow the readme instructions. One thing not mentioned is that the actual compiled module is in the precompiled/eggdrop 3/ directory.You need to move this to /usr/lib/eggdrop/modules/

Then you must edit the logs2html.conf script and the chan.list file. You must also re-edit the eggdrop.conf file and add a line in the end that contains:

source logs2html.conf

When you are done, you should be able to view your irc logs on a website as defined in chan.list. There is an example here: www.nubae.com/logs


Rate It! (Average 0, 0 votes)



PHP logbot for IRC Channels

I tend to hang out a lot on the #ltsp IRC channel, and I found myself remembering some interesting things that were said, but since there are no logs on the web, there was no way to review the chat histories. The only option was to set up a irc log bot and create a webpage that would stream the content of the irc logbot to it. I found a great little php logobot, which after some tweaking worked quite well. The main issue with it is that it requires a frontend to be created for it that pulls all the logged data from a mysql database in some way. There are many ways to do this, including using various php frameworks, or even another language entirely, but for now, I decided to code something later on down the line that includes an archive of the logs including paginations and the like.

To run the bot, one requires the NET_SmartIRC pear class, which can be installed doing:

pear install NET_SmartIRC

The bot requires an SQL import (you can do that with phpmyadmin for example) with the following:

DROP TABLE IF EXISTS `irc_log`;
CREATE TABLE IF NOT EXISTS `irc_log` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `nick` varchar(32) NOT NULL default '',
  `ident` varchar(64) NOT NULL default '',
  `host` varchar(254) NOT NULL default '',
  `type` varchar(4) NOT NULL default '',
  `from` varchar(254) NOT NULL default '',
  `channel` varchar(32) NOT NULL default '',
  `message` text NOT NULL,
  PRIMARY KEY  (`id`),
  FULLTEXT KEY `nick_msg` (`nick`,`message`)
)DEFAULT CHARSET=utf8;



Here is the code for the bot. This was created by someone else, but I changed a couple of things so it will run on Debian. Remember to change the user and channel details in the beggining and end of the script and then run by doing:

php irclogbot.php

'<'?php /**="" *="" an="" irc="" logbot="" based="" on="" pear::net_smartirc="" logs="" channel="" to="" a="" mysql="" database,="" triggered="" by="" "actionhandler"s="" as="" implemented="" in="" smartirc.="" actionhandler="" values="" are="" defined="" net_smartirc/smartirc/defines.php="" normal="" conversation="" can="" be="" caught="" smartirc_type_channel,="" /me="" is="" smartirc_type_action="" there="" currently="" no="" logging="" for="" joins/quits/etc.="" this="" script="" has="" been="" written="" server="" with="" php="" version="" 4.4.0-4="" and="" 4.1.15="" @author="" chris="" prior="" 
 *
 */

//include the pear class (doesn't need an include_path for that dir)
include_once('/usr/share/php/Net/SmartIRC.php');

class irclogbot extends Net_SmartIRC

{
  var $hasDbConn=false;
  var $mysql_host='localhost';
  var $mysql_user='changeme';
  var $mysql_password='changeme';
  var $mysql_db='changeme';
  var $mysql_table='irc_log';
  var $log_obj;
  var $stats_obj;
  var $loggables=array('nick','ident','host','type','from','channel','message');
  var $logfileIfMysqlError='errorMysqlINSERT.log';

 //function irclogbot(&$log_obj,&$stats_obj2){
  //}

  /*
   * overwriting existing function
   */

  function _nicknameinuse()
  {
      $newnickname = $this->_nick.'_';
      $this->changeNick($newnickname, SMARTIRC_CRITICAL);
      $this->_register();
  }



  //unused
  function _register()
  {
      $this->_send('/msg NickServ IDENTIFY changeme', SMARTIRC_CRITICAL);
  }

 /*
   * Basic MySQL auth
   */

  function connect_database()

  {
      $link = @mysql_connect($this->mysql_host, $this->mysql_user, $this->mysql_password)
         or die("Keine Verbindung möglich: " . mysql_error());
      $this->hasDbConn = @mysql_select_db($this->mysql_db) or die("db select failed.");
  }



  /*
   * the workhorse logging method
   *
   * Checks for content of $data-> object as returned from PEAR class,
   * constructs a SQL statement and inserts with connection check
   * Outputs some stuff to stdout
  * Don't confuse the 2 stdout sources: parent::setDebug also does it!
   *
   * never change the methodname to 'log', incompatible to the PEAR class!
   *
   */
  function my_log(&$irc='',&$data='')
  {
    $doit=true;
    //quick hack to filter out server msg marked S*_TYPE_CHANNEL
    foreach($this->loggables as $v){
      if (!isset($data->$v)) $doit=false;
      //else echo "$v has " . $data->$v."\n"; //debug
    }

    if($doit){
      //there is an 'ACTION' prefix for the message, I strip it.
      //To recognize a type `action` I still have the value 256 in the col `type`
      if(256==$data->type) {
        $data->message = substr($data->message,8);
        $data->message = substr($data->message,0,strlen($data->message)-1);
        }//end if type 256 == action

      /**
       * The following does not work if there is no db link,
       * so I use mysql_real_escape_string selectively.
       * This leaves the error log unescaped!!!
       *
      */
      //split for original debugging as above, could be merged into one foreach
        foreach($this->loggables as $v) {
        //http://php.net/manual/en/function.stripslashes.php#51390
        if (get_magic_quotes_gpc())
          $data->$v = stripslashes($data->$v);
        //can't use it on the ready query as it would return
        // *VALUES '\'myNickName\',*
        if(!is_numeric($data->$v) AND $this->hasDbConn )
          $data->$v = @mysql_real_escape_string($data->$v);
      }
    }//end if $doit
    //no linebreaks or mysql_real_escape_string breaks the statement!
    $sql = sprintf("INSERT INTO %s "
      . "(`nick`, `ident`, `host`, `type`, `from`, `channel`, `message` ) "
      . " VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s');",
      $this->mysql_table,
      $data->nick,
      $data->ident,
      $data->host,
      $data->type,
      $data->from,
      $data->channel,
      $data->message
    );
    //echos to stdout
    echo $sql;

    /**
     * Now we are fighting hard to preserve the log
     */
    //the mysql INSERT query
    if(!$this->hasDbConn){
      $irc->connect_database();
      if(!$this->hasDbConn){
        $this->logInsertIfMysqlError($sql);
      }
    }
    //new if, not elseif, so a success above triggers
    if($this->hasDbConn == true AND $doit)
    {
      //echo "hasDbConn\n";
      $result = @mysql_query($sql);
      if (!$result) {
        echo('invalid query: ' . mysql_error());
        $this->logInsertIfMysqlError($sql);
      }
    }//end if hasDbConn*

    else {

      $this->logInsertIfMysqlError($sql);

      echo "\n WARNING! Has no DB connection! WARNING!\n";

    }

    echo "\n\n";

  }

  /**
   * Fallback if no MySQL conn
   *
   * I got an 'invalid query: MySQL server has gone away' after long a silence.
   * This is to preserve the INSERT statements for later addition to the db.
   */
  function logInsertIfMysqlError($content){
    echo "Trying to log into error logfile ".$this->logfileIfMysqlError."\n";
    if(!file_exists($this->logfileIfMysqlError)){
      if (touch($this->logfileIfMysqlError) === false){
        echo "cannot touch the non-existing file!"."\n";
        continue;
      }
    }
    if (!is_writable($this->logfileIfMysqlError)) {
       if (!chmod($this->logfileIfMysqlError, 0666)) {
         echo "Cannot change the mode of file ($this->logfileIfMysqlError)"."\n";
         continue;
       };
     }
     if (!$fp = @fopen($this->logfileIfMysqlError, "a")) {
       echo "Cannot open file ($this->logfileIfMysqlError)"."\n";
       continue;
     }
     if (fwrite($fp, $content."\n") === FALSE) {
       echo "Cannot write to file ($this->logfileIfMysqlError)"."\n";
       continue;
     }
     else echo "ERROR LOGGED! Wrote into ".$this->logfileIfMysqlError."\n";
     if (!fclose($fp)) {
       echo "Cannot close file ($this->logfileIfMysqlError)"."\n";
       continue;
     }
  }//end function

  /**
   * Calling this at startup might catch the worst scenario and
   * renders the above logInsertIfMysqlError($str) useless in many respects
   */
  function testForErrorLogfile(){
     if (!$fp = @fopen($this->logfileIfMysqlError, "a")) {
       echo "Cannot open file ($this->logfileIfMysqlError)"."\n";
       exit;
     }
  }//end function
  //doesn't work as expected, but I don't care
  function my_quit(&$this, &$ircdata)
  {
    echo 'FooBar';
    $this->quit("The Bot has quit.");
  }
}//end class ######################################

$irc = &new irclogbot();
$irc->testForErrorLogfile();

//$irc->connect_database();
//pear/Net_SmartIRC/SmartIRC/defines.php
$irc->setDebug(SMARTIRC_DEBUG_NOTICE|SMARTIRC_DEBUG_CONNECTION|SMARTIRC_TYPE_ACTION|SMARTIRC_TYPE_CHANNEL);
$irc->setUseSockets(TRUE);
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '^sfLog: !quit',
$irc, 'my_quit');

//pear/Net_SmartIRC/SmartIRC/defines.php
//SMARTIRC_TYPE_CHANNEL is defined as `2` and this gets inserted into the db
//never change the methodname to 'log', as it is incompatible to the PEAR class
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '^.?', $irc, 'my_log');


//type channel does not catch /me et al.
$irc->registerActionhandler(SMARTIRC_TYPE_ACTION, '^.?', $irc, 'my_log');
$irc->connect('irc.freenode.com', 6667);

//Usage: login(nick, realname, usermode, username, password);
$irc->login('editme', 'ltsp logger');
$irc->join(array('#editme'));
$irc->listen();
$irc->disconnect();
?>

Rate It! (Average 0, 0 votes)



Installing the Moodle Virtual Learning Environment on Ubuntu Linux

What is Moodle?

Moodle is commonly referred to as a virtual learning environment (VLE), and is extremely useful for educational institutions. It allows teachers to setup their course materials electronically so that students can then involve themselves virtually with all aspects of it. Materials can be put in almost any format imaginable, be it videos, exam papers, podcasts or normal written lectures. And since it is interactive, users can leave feedback and communicate with each other through many means, including chat rooms, blogs, wikis, and forums. For a full list of features, visit: www.moodle.org

Installation

Installing moodle on Debian and Ubuntu is fairly easy. Do

sudo apt-get install moodle

and it should pull all the required dependencies in with it. During the installation you will be asked various questions.
1.Choose Apache 2

2.Choose Postgres or Mysql as database. Postgres is useful for larger deployments.

3.Default mysql or postrgres database created? Answer: Yes

4.username: Moodle

5.password: ****

The installation should go through, but sometimes the database needs to be created manually. Try sudo apt-get install moodle first, and otherwise use the database administration tools to create the database and user selected above. Your setup is now ready and you must continue with the web based installation by going here with your browser:

http://localhost/moodle/admin

Accept the license agreement.and keep clicking continue until you reach the setup administrator account. Fill in the relevant details, noting username and password. Next fill in the Site details.

Congratulations, your Moodle site is installed and ready to start entering courses and students.

Rate It! (Average 0, 0 votes)