This occasionally comes up in conversation and I can never remember so I'm just going to store it here for future reference.

The median Erdös number is 5; the mean is 4.69, and the standard deviation is 1.27.

My Erdös number is 4.

McConville, Ryan; Liu, Weiru; Miller, Paul Vertex. Clustering of Augmented Graph Streams, Proceedings of the 2015 SIAM International Conference on Data Mining (2015), pp. 109-117

Cheng, Jie; Greiner, Russell; Kelly, Jonathan; Bell, David; Liu, Weiru. Learning Bayesian networks from data: an information-theory based approach. Artificial Intelligence 137 (2002), no. 1-2, 43–90.

Greiner, Russell; Hayward, Ryan; Jankowska, Magdalena; Molloy, Michael. Finding optimal satisficing strategies for and-or trees. Artificial Intelligence 170 (2006), no. 1, 19–58.

Alon, N.; Erdős, P.; Gunderson, D. S.; Molloy, M. A Ramsey-type problem and the Turán numbers. J. Graph Theory 40 (2002), no. 2, 120–129.
This was posted on Wed 02 Aug 2017 (1 year, 10 months ago) by Ryan McConville
Recently the University of Bristol made the switch from the Google to Microsoft platform for email, calendar etc.
As a user of mutt the impact was somewhat minimal for me but I did have to figure out the new settings to get offlineimap to sync my mail and mutt to send it.

Here is what worked for me.

[Account bristol]
localrepository = bristol-Local
remoterepository = bristol-Remote
status_backend = sqlite
maxsyncaccounts = 6

[Repository bristol-Local]
type = Maildir
localfolders = ~/Mail/bristol

[Repository bristol-Remote]
type = IMAP
remoteuser =
remotepass = password
remotehost =
remoteport = 993
realdelete = no
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
folderfilter = lambda folder: folder in ['INBOX', 'Sent', 'Drafts', 'Sent Items', 'Junk E-Mail']

I use mutt directly for SMTP and the settings that work for me are
set smtp_url = "smtp://"

Hopefully this helps someone else who knows mutt is the one true way of working with email :)
This was posted on Sun 23 Jul 2017 (1 year, 10 months ago) by Ryan McConville
You can use the Inkscape extension Tex Text to insert and render LaTeX within your Inkscape graphics.

You can find the latest version here. I'll include all the commands I ran below to get this up and running with the current latest version of Tex Text and Inkscape 0.91 r13725


tar -xvzf textext-0.4.4.tar.gz

cp textext.inx .config/inkscape/extensions/

Restart inkscape (if required).

Within Inkscape and you can find the new extension under Extensions > Tex Text.
Type in some LaTeX text and it will insert the rendered text into your document.
This was posted on Fri 08 Jan 2016 (3 years, 5 months ago) by Ryan McConville
I have a lot of data and I would like to keep this data safe. For example, I have way too many pictures going back way too long, and I would like to keep these forever!

That means I need a good data backup strategy, and for this I have mostly settled on a combination of tools and scripts. Perhaps I'll write about my backup strategy in detail in the future. For this post it will suffice to say that the tool which handles the backup is duplicity (bonus, encrypted!) and one of the remote locations it backs up to is, which I highly recommend.

So far, can accept my data at the fastest rate I can push it. However this typically means that the rest of my Internet experience suffers when backups are running as my bandwidth is being saturated.
I had a little look around and came across a nice little tool called tricke which can limit the download/upload bandwidth of a process, all in userland!

It seems to be quite configurable but all I had to do was prepend 'trickle -u 800' to my backup scripts to limit duplicity to using at most 800Kb/s of my upload bandwidth. I quickly verified this with nethogs. Perfect!
This was posted on Fri 08 Jan 2016 (3 years, 5 months ago) by Ryan McConville
So QUB have begun rolling out a new WiFi solution across the campus, deprecating qub_sec.
The settings for _QUB_WIFI have changed, so for convenience sake I'll list them here.

EAP Method (Authentication): PEAP
Phase 2 Authentication: MSCHAPv2
Identity: student number
Anonymous Identity: leave blank
Wireless Password: your password

Unlike before, after the first time you connect to _QUB_WiFi you need to sign in via some sort of web based portal. Going straight to Google or Facebook won't work due to HTTPS, so try in order to be redirected to the _QUB_WiFi sign in page.

I've tested this on my Linux computer and Android phone.
This was posted on Thu 07 Jan 2016 (3 years, 5 months ago) by Ryan McConville
While I do have off-site backups for, why not take the safety of your data into your own hands?

Here I will quickly document a simple method of backing up all your link data stored in LinkiePie using the API. As mentioned in a previous post you can access your API key in the settings page (

Using this API key you can issue a request to access a JSON blob of all your data. Let's use curl in a simple shell script to download it and save it to your home directory.
#!/usr/bin/env sh

curl -s "" -o "$HOME/linkiepie_backup.json"
This will save a JSON file containing all of the links (and associated data) you have added to LinkiePie. This includes data such as the URL and extracted summary text of each link.

Depending on how much you use LinkiePie this may be quite a large file. I like to use an awesome tool called jq for exploring and extracting useful information from JSON files. Here's an example of using jq for extracting just the URLs from this file.

cat linkiepie_backup.json | jq '.objects[].url'

You can add the above sh script to cron for automatic periodic backups.

Easy :)
This was posted on Wed 06 Jan 2016 (3 years, 5 months ago) by Ryan McConville
Newsbeuter is an open source RSS feed reader for terminals.
It's great for quickly consuming lots of information from websites. One nice feature is that it allows you to 'bookmark' specific links, and that's where LinkiePie comes in.
LinkiePie is a personal project of mine for storing and organising links, somewhat like Pocket and Instapaper, and I would like to send my links directly from newsbeuter to it.
It has a basic API for externally accessing some functionality and accounts are automatically generated API keys. The following is a quick guide for sending your bookmarked newsbeuter links straight to your LinkiePie account.

The first step, of course, is to get a LinkiePie account. When you have registered check out to get your API key. This is all you need to programmatically add and retrieve your links with LinkiePie.

Next we will setup a simple script that will interface with newsbeuter. Save the following code in a convenient directory or download it from here.
curl -k -H "Content-Type: application/json" -X POST --data "{\"url\": \"${URL}\"}" "${USERNAME}&api_key=${API_KEY}"

Make sure to change YOUR_USERNAME and YOUR_KEY to your own details.
Assuming you have the script in a file called and have placed it in your home directory, the next step is to update your newsbeuter config file (.newsbeuter/config) with the following:
bookmark-cmd "~/"
bookmark-autopilot yes

The final step is to set the executable bit on the script so newsbeuter can execute it.
chmod +x

Restart newsbeuter and try it out by pressing Ctrl+B with an article highlighted or selected. You should then see that article in your LinkiePie account along with an archived version of the important text.

You can retrieve your data from LinkiePie via the API as well. The following request will return the the url, title and extracted text from the links you've added.

The number of results returned for each request is controlled by the limit parameter and adjusting the offset parameter, which specifies where in the list of results to start from, will allow you to move between these sets of results.
This was posted on Tue 16 Dec 2014 (4 years, 6 months ago) by Ryan McConville
Using dbus and ConsoleKit it's easy to power off your computer from the terminal. This is useful when you're not using a desktop like GNOME or Unity and you want to shutdown without superuser privileges.

dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop

Of course it's probably a good idea to create an alias for this rather long command.

alias turnoff='dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop'

For the sake of completeness you can also restart and suspend your computer using dbus and ConsoleKit.

To restart use:
dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Restart

To suspend use:
dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Suspend

This was posted on Sun 30 Nov 2014 (4 years, 6 months ago) by Ryan McConville
I wanted to use the key combination 'Fn+F2' to lock my computer with xscreensaver, but wasn't sure how to represent this key combination in the awesome wm rc.lua configuration file. Unfortunately you can't just insert combinations using 'Fn' like you would 'Ctrl', instead you must use the relevant 'Fn' combination keycode.

It turns out that you can use a tool called xev to print out events such as keypresses that occur in a X11 window. Running xev and pressing the desired key combination will output to a terminal information for this event, including the keycode. Doing this I discovered that 'Fn+F2' translated into keycode 160.

Adding the following to the key binding section of my rc.lua worked great.
awful.key({}, "#160", function () awful.util.spawn("xscreensaver-command -lock") end),
This was posted on Fri 31 Oct 2014 (4 years, 7 months ago) by Ryan McConville
A quick and easy way get a readable version of a webpage directly from your terminal is to use the dump argument of the lynx text based web browser.

This is great for times when you are working from your terminal and want to view a website, for example to view a link received via IM, but would prefer not to leave your terminal to do so.

While tools like curl and wget will return the HTML file, including the HTML tags, lynx will parse it and return a much more readable version.

The following will output a readable version of this webpage directly to your terminal via stdout.
lynx -dump


Sometimes you may want to save a readable copy of a webpage to a text file to read later. This can be done by redirecting stdout to a file.
lynx -dump > blog.txt

Lynx can also be used interactively for browsing the web by dropping the dump argument. For a program that predates the world wide web, it works suprisingly well on many modern websites.
This was posted on Thu 30 Oct 2014 (4 years, 7 months ago) by Ryan McConville
Sometimes I am running experiments on a remote computer but doing the analysis of the experiments on
a local computer. Rather than manually copying or periodically syncing the results data for analysis, it's easier to mount the remote directory locally so that the remote files can be treated as if they are on the local filesystem. SSHFS (SSH Filesystem)
is one such tool that allows you to do this. All you need is SSH access to the remote server and SSHFS installed on the client.

The following instructions were tested on Ubuntu 12.04.
apt-get install sshfs
Now that sshfs is installed we can use it to mount the remote filesystem locally. First we will make a directory where we would like the remote filesystem mounted.
mkdir ~/rfs
Now we use sshfs to mount the remove filesystem...
sshfs user@dest:/dir/anotherdir ~/rfs
..and lets check the contents of the remote directory we just mounted.
ls ~/rfs
If you want to unmount the remote filesystem you can do so with the following...
fusermount -u ~/rfs
This was posted on Wed 03 Sep 2014 (4 years, 9 months ago) by Ryan McConville
EDIT: qub_sec has been deprecated and replaced by _QUB_WiFi. You can find the settings for _QUB_WiFi here.

The settings for the Queen's University Belfast wireless network can be hard to find (for me at least) and when actually found the settings are buried in some PDF file, so I'm posting them here for convenience.

EAP Method: TTLS
Phase 2 Authentication: PAP
Identity: student number
Anonymous Identity: leave blank
Wireless Password: your password

You can optionally choose to use the CA Certificate to verify the authenticity of the qub_sec connection. I'm hosting a copy here for my own conveience .

The names of the fields above are from my Android phone, and they are similar using NetworkManager on Linux. I haven't tried on iOS but it's probably similar too.
This was posted on Sun 24 Aug 2014 (4 years, 9 months ago) by Ryan McConville
Tags: Tech Notes
If you prefer Debian over Ubuntu (and Ubuntu derivatives) but like the appearance of Xubuntu, then here’s some steps for making Xfce on Debian Wheezy look a lot more like Xubuntu. These steps are far from complete, but they make it look close enough to the default appearance of Xubuntu for me.

I’m going to assume you already have Xfce installed. I typically do this during the Debian install procedure but if you didn't do that you can still replace the default GNOME desktop environment with Xfce. Here’s a nice overview of how to do both. The key to the appearance of Xubuntu is the Greybird Xfce theme that it uses by default. I prefer to get the latest version directly from the Github repository of The Shimmer Project rather than relying on potentially older packaged versions.

First let's get the theme itself.
su -c 'mv Greybird-master /usr/share/themes/'

Now, let's get the Greybird icons.
su -c 'mv elementary-xfce-master/* /usr/share/icons'

The next step is to enable the theme. First go to Settings->Appearance and select 'Greybird-master' under the 'style' tab. Then under the ‘Icons’ tab select 'elementary Xfce dark'. Under the 'fonts' tab I typically enable anti-aliasing, set hinting to slight and set the sub-pixel order to RGB.

After doing this, you should be seeing a theme that looks similar to Xubuntu, but not quite. The next step is to go to Settings->Window Manager and under 'style' select 'Greybird-master'.

After doing this I find that my Debian installation looks close enough to Xubuntu for me, and certainly much better than the rather dated default Xfce theme.

This was posted on Sat 19 Jul 2014 (4 years, 11 months ago) by Ryan McConville
The default setting on many SSH servers is to disconnect clients who have been inactive for a set period of time. If you ever left an SSH client running without interacting with it for a while, only to find a message such as Connection reset by peer, then this is likely the cause. I find the easiest way to prevent this is to configure your SSH client to send a null packet to the SSH server, almost like a heartbeat. Edit your ssh_config file setting ServerAliveInterval to:
ServerAliveInterval 60
and ServerAliveCountMax to
ServerAliveCountMax 3
ServerAliveInterval tells your SSH client to send a message every 60 seconds to the SSH server thereby preventing the server from disconnecting you for being idle. I chose the value of 60 but you can increase or decrease this as required. ServerAliveCountMax is the number of times to send the null packet and receive no response, before giving up.
This was posted on Wed 25 Jun 2014 (4 years, 11 months ago) by Ryan McConville
Tags: Tech Notes
I was thinking about how the Bing Desktop application manages to retrieve the Bing image each day, so I used Wireshark to monitor the application as it runs. I noticed that it retrieves an XML document from, which provides the URL for the image. Using this I updated my script I originally posted here. It also looks like we can retrieve the higher resolution 1920x1200 image with this URL from outside the USA too.

import urllib2
import os
import sys
import shutil
import argparse

from xml.dom import minidom

def main(save_location):
bing_url = ''
xml_url = ''

xml = urllib2.urlopen(xml_url)
xml_doc = minidom.parse(xml)
url_base = xml_doc.getElementsByTagName('urlBase')[0].firstChild.nodeValue
extension = xml_doc.getElementsByTagName('url')[0].firstChild.nodeValue.split('.')[-1]
image_url = bing_url + url_base + '_1920x1200.' + extension

img = urllib2.urlopen(image_url)
except urllib2.HTTPError as e:

image_name = image_url.split('/')[-1]

if not os.path.exists(save_location):

if save_location[-1] != '/' or save_location[-1] != '\\':
save_location += '/'

with open(save_location + image_name, 'wb') as f:
shutil.copyfileobj(img, f)

if __name__ == "__main__":
script_dir = os.path.dirname(os.path.realpath(__file__))
parser = argparse.ArgumentParser(description='Download todays Bing image.')
parser.add_argument('-d', '--dir', dest='save_location', action='store',
help='Directory to store the downloaded image (default: directory of this program)')

results = parser.parse_args()


You can also find the repository at
This was posted on Tue 24 Jun 2014 (4 years, 11 months ago) by Ryan McConville
Tags: code
When working with an SQLite3 database I occasionally forget a column name that I need to know. This tends to be followed by being unable to remember how to find out column names (and other information) for a table. Future me, here's how to do it.

If you know the table name, great. If not, you can ask SQLite3 to list all tables with the following command:

Once you know the table name, you can find the table information with the following:
PRAGMA table_info(table-name);

Each column in the table is printed out on a new row as follows:

A real world example:

More information on this can be found here:
This was posted on Tue 24 Jun 2014 (4 years, 11 months ago) by Ryan McConville
Tags: Tech Notes
As part of my research I tend to be working with relatively large files. One 150GB file I work with particularly often involves moving an updated version of it from one directory to another. On my Ubuntu desktop this causes everything to become unresponsive for the duration of the transfer.

One solution to this is ionice which lets you set the IO priority of processes. It's kind of like regular nice but for IO specifically. I found that the follow command, which sets the scheduling class to be 'Idle', let my desktop remain completely responsive while the transfer was taking place.

ionice -c 3 cp $src_file $dst_directory
This was posted on Tue 24 Jun 2014 (4 years, 11 months ago) by Ryan McConville
On the 24th of April 2012, I published an Android application, that I developed over the course of a week, onto the Android store. I initially developed it for my own use as I thought it would be cool to see the daily featured Wikipedia article on my phone homescreen each day. For almost a year I got very few downloads, and I kind of expected that. However I kept publishing updates as I discovered bugs and thought of improvements, such as adding in the 'today in history' section as an option.

A couple of these updates must have been useful, as a few of them resulted in a spike in the number of downloads. These can be seen in the image below.

install graph

At this moment in time I have over 15,000 installs, with around 30% of users still having it installed. I'm quite surprised I have got so many downloads, and I feel somewhat guilty for not continuing to make improvements due to being occupied with other things.

Oh, and the link to the application on the Play store is:

This was posted on Tue 24 Jun 2014 (4 years, 11 months ago) by Ryan McConville
Continuing in my effort to create blog posts of old bits of code I can find lying around on my computer and internal git server, I decided to post this small C++ project. It logs the percentage of battery left at specific intervals into a SQLite3 database. Again, this is one of my first C++ projects so I'm not exactly confident it's done to a high standard. :)

Nonetheless, the code is included below and a the git repository on bitbucket can be found here:

#include "stdafx.h"
#include "iostream"
#include "sstream"
#include "time.h"
#include "vector"
#include "iostream"
#include "Windows.h"
#include "fstream"
#include "Shlobj.h"
#include "stdio.h"
#include "WbemCli.h"
#include "sqlite3.h"

using namespace std;

//get the users home directory
wstring GetHomeDirectory(){
PWSTR path;
SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &path);
return path;

void WriteDefaultConfiguration(char *defaulttime){
ofstream config_file;"config.ini", ios::out);
config_file.write(defaulttime, strlen(defaulttime));

int ConvertToMilliseconds(int interval){
return ((interval * 60) * 1000);

int ReadConfigurationFile(){
char defaulttime[7] = "10";
char line[7];
ifstream config_file;"config.ini",ios::in);
return ConvertToMilliseconds(atoi(defaulttime));
config_file.get(line, 10);
int interval;
interval = atoi(line);
int interval_milli = ConvertToMilliseconds(interval);
return interval_milli;

sqlite3* CreateDatabase(){
sqlite3 *db;
char *err = 0;

int rc = sqlite3_open("battery_stats.sqlite", &db);

fprintf(stderr, "cant open database %s\n", sqlite3_errmsg(db));

char *sql = "CREATE TABLE IF NOT EXISTS stat(" \
"battery_percentage INT NOT NULL," \
"ac_connected INT NOT NULL);";

sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, sql, -1, &statement, 0) == SQLITE_OK){

return db;

int _tmain(int argc, _TCHAR* argv[]){

//hide console window
HWND hWnd = GetConsoleWindow();
ShowWindow(hWnd, SW_HIDE);
int interval_time = ReadConfigurationFile();
sqlite3 *db = CreateDatabase();

::GetSystemPowerStatus(&status);//get battery life
int per = status.BatteryLifePercent;
//get time
time_t rawtime;
struct tm* printtime;
printtime = localtime(&rawtime);
string timenow = asctime(printtime);
//create structure to hold percentage as a string
char strPer[4];
//copy int percentage to string
itoa(per, strPer, 10);
//open textfile to write to
ofstream batteryStats; +L"/battery_stats.txt", ios::app);
int AC = (int) status.ACLineStatus;
string acconnected;
acconnected = "AC connected";
acconnected = "AC disconnected";

cout<< "Error";
batteryStats << "\n" << timenow < }

sqlite3_stmt *statement;
char *sql = "INSERT INTO stat (date, battery_percentage, ac_connected) VALUES(?, ?, ?);";
if(sqlite3_prepare_v2(db, sql, strlen(sql), &statement, 0) == SQLITE_OK){
sqlite3_bind_text(statement, 1, asctime(printtime),strlen(asctime(printtime)), 0);
sqlite3_bind_int(statement, 2, per);
sqlite3_bind_int(statement, 3, AC);

} else {
fprintf(stderr, "cant update database %s\n", sqlite3_errmsg(db));

//sleep for specified time

This was posted on Tue 24 Jun 2014 (4 years, 11 months ago) by Ryan McConville
A few years ago, when learning Python, I wrote a little script that will retrieve and save to disk the current background image. The directory where the image is saved is the first argument. You can run it via cron if you use a Linux based OS or via Windows Task Scheduler if you use, well, Windows.

I did notice that if you access from a USA IP address then you have the ability to retrieve a higher resolution 1920x1200 image, whereas from the UK (and likely elsewhere) you can only access the 1366x768 image.

import re
import urllib2
import os
import shutil
import sys

bing_url = ''
save_location = sys.argv[1]

p = re.compile('/az/.+?(jpg)')
resp = urllib2.urlopen(bing_url).read()

image_url =
if '_EN-US' in image_url:
res = image_url.split('_')
extension = image_url.split('.')[-1]
image_url = '_'.join(res[:-1]) + '_1920x1200.' + extension

img = urllib2.urlopen(bing_url + image_url)
except urllib2.HTTPError as e:
print e

image_name = image_url.split('/')[-1]

if not os.path.exists(save_location):
with open(save_location + image_name, 'wb') as f:
shutil.copyfileobj(img, f)

Edit: I have since updated this script with some nice new changes. You can find that post here:
This was posted on Mon 23 Jun 2014 (4 years, 11 months ago) by Ryan McConville
Last week my Queen's University Belfast (QUB) IMAP settings stopped working. After tracking down that this was the reason I wasn't receiving new emails, I discovered the following IMAP and SMTP settings which now work. I have tested these settings with Outlook, Thunderbird and my Android phone. I assume they will also work with iOS and OSX clients too.

Note that there seems to be two different types of email accounts currently in use within QUB, but the following should work for 'Office 365' accounts, i.e. the new ones.

Server name:
Port: 993
Encryption method: SSL

Server name:
Port: 587
Encryption method: STARTTLS

User name:

Staff Accounts
Here are the settings that work for me to get staff email to work over IMAP/SMTP.
Server name:
Port: 993
Encryption method: SSL/TLS

Server name:
Port: 587
Encryption method: STARTTLS

User name: staff number
This was posted on Mon 23 Jun 2014 (4 years, 11 months ago) by Ryan McConville
Tags: Tech Notes
Here is a copy of my PGP public key. If you don't know what that is and would like to learn more then I suggest reading this. This website is currently served over HTTPS so it should be reasonably secure method of sharing the key. You can also find it in all the usual places, such as the MIT key server here.
Key fingerprint = F2B4 BD37 3C2B 141E FD97 6B58 DFDE 9735 A4F0 944D

Version: GnuPG v1

This was posted on Thu 20 Mar 2014 (5 years, 2 months ago) by Ryan McConville
Tags: PGP
Recently I got an Acer C720 Chromebook and wanted to write a little bit about what I think of it. Basically, it's a small 11.6 inch screen laptop but instead of running a more typical operating system such as Windows 7 or Debian/Ubuntu (more on that later), it runs an operating system from Google called ChromeOS. To the user, it's pretty much just the Chrome web browser with some basic but nice operating system type features around it, such as a lock screen and notification area. While the world seems to be heading towards a cloud-based-always-online type environment, I'm not so keen on that idea on my own personal computers. So why did I get it? I got it because of its low price point (~£200), good battery life, good build quality, and its ability to run a more conventional operating system such as Debian or Ubuntu.

First, the build quality feels very good for the price point. I have used laptops that cost twice the price but don't feel as well built. It has a very plain appearance, definitely not as quirky and fun as it's competitor the HP Chromebook 14, but that's a positive for me. It's weighs just over 1.1 kg, which is a nice change compared to my older laptop that weighs about 2.7 kg. So while I may notice and appreciate the lightness more than some, I find it very portable. The 11.6 inch screen has a resolution of 1366x768 so while the pixel density for the screen size is pretty good, the quality of the display itself leaves a lot to be desired due to the dull washed out colours and poor viewing angles. The battery life on the C720 is fantastic however and I'm getting around 8 hours of use on a full charge, not much less than Acers claimed 8.5 hours.

To be honest, I haven't spent very much time in ChromeOS since my current way of working just doesn't fit into the web based workflow that ChromeOS kind of forces you to have. However, what I did see in the short time I used it was promising. The experience was smooth and everything worked nicely. I would have no hesitations recommending it to someone who doesn't need access to a more traditional operating system. However not using ChromeOS much doesn't mean I haven't been using the C720 chromebook much! In fact, it's quite the opposite. One of the first things I done when I unboxed it, after a quick tour of ChromeOS, was setup Ubuntu using crouton.

Crouton is a set of scripts that makes setting up a chroot extremely easy. If you aren't familiar with what a chroot is, don't worry. Crouton has abstracted away all of the messy details and all you really need to know is that it's a way of getting another Linux distribution running on your chromebook. It requires enabling 'developer mode' and you can do this by holding down esc and refresh and then pressing the power button. This puts it into 'recovery mode' and if you press CTRL+D at the recovery screen, you will reboot into ChromeOS with developer mode enabled. This process wipes all user data stored on the device including ChromeOS user accounts. Once you are running ChromeOS with developer mode enabled you can follow the instructions found in the README in croutons github repository to get your new operating system up and running.

However a brief overview of the steps required is as follows:
Download the crouton script from the following URL: This will save to your 'Downloads' directory.

Open a crosh shell using CTRL+ALT+T in ChromeOS and then type shell. Note this only works in developer mode.

Now type sudo -e ~/Downloads/crouton -r precise -t unity -e .

This will install the 'precise' release of Ubuntu with the Unity desktop. The final -e switch encrypts the chroot.

Simply running sudo -e ~/Downloads/crouton will provide you with more information, including how to find out about other releases that you can install.
The rest is pretty much automated and after it's complete you will have your chroot setup.

I typically enter my chroot with the command sudo -b startunity. The -b switch backgrounds the process so you can close the ChromeOS tab.

You can switch between the chroot and ChromeOS with CTRL+SHIFT+LEFTARROW and CTRL+SHIFT+RIGHTARROW.

Since the C720 has a x86 CPU, it doesn't suffer from having a restricted set of applications like ARM based chromebooks when running an OS like Debian. The C720 contains a dual core 1.4GHz Celeron CPU (2955U) with the current generation Intel Haswell microarchitecture making it an efficient and capable little device. So while I won't be keen to run any very intensive tasks on it, due to the limited 2GB of RAM and 16GB of SSD storage, it can run pretty much all of the applications you would expect.

While using crouton does have a negative effect on the default security of the device, you can take steps to recover some security. These are just some general tips and in no way comprehensive. First, make sure you set a root password on ChromeOS since it's not set by default when developer mode is enabled. You can do this with the following command:
sudo chromeos-setdevpasswd
Crouton supports encryption of your chroot and this is done by using the -e switch with the crouton script.
When using Unity on 12.04 I found that it was not possible to lock your computer on a default install, but that can be solved by installing the relevant package (gnome-screensaver) manually.

In summary, I am very happy with the C720 as it's a lightweight, long lasting and reasonably well performing Linux laptop.
This was posted on Tue 11 Feb 2014 (5 years, 4 months ago) by Ryan McConville
So as a follow up to my previous post, I decided that it would be a good idea to write a little bit about a project that I spent some of my free time working on. Now that I have started my PhD I have less time for working on side projects, so this is probably a good landmark. It's called LinkiePie ( and I started it whenever I was compiling links for the 'stuff I have found interesting recently' posts on my blog. The idea of LinkiePie is that it's a place to store, organise and categorise interesting stuff you find on the web.

Basically, a LinkiePie is a list where you store the links to the interesting stuff you come across on the web, and you can create as many of them as you want. So, for example, you can have a LinkiePie for links related to a specific web development technology you like, or one for links related to some topic you are researching, or maybe a LinkiePie for links you think some of your friends would like.

You can also make your LinkiePies public so that you can share them with others. Making it public will give you a URL that you can send to someone else and they will be able to see whatever you put into that LinkiePie.

One other feature I thought would be pretty cool is grabbing the relevant content of the page that you are storing. So if it disappears or changes in the future, you still have a copy of what you found interesting at the time.

This is very much a work in progress, but as I said, I thought I would write about what I have done so far.

Here are two LinkiePies for the first two 'stuff I have found interesting recently' posts on my blog.
This was posted on Tue 12 Nov 2013 (5 years, 7 months ago) by Ryan McConville
I decided that instead of taking an industry job after I graduated I would instead embark on a PhD in Computer Science. As much as I really enjoy writing code, and software engineering in general, the opportunity to do research in CS was just too appealing to turn down. Research is something that has interested me for some time now and working on my undergraduate final year project helped convince me that I wanted to continue in academia. Of course I will still be writing code throughout my PhD (both academically and as a hobby) so it's a win-win in my mind. I'm really looking forward to the challenge.

Broadly speaking, the topics in which I am interested are data mining, machine learning, anomaly detection and graph theory.

It has been a few weeks since I have started and I'm enjoying it a lot.
This was posted on Wed 23 Oct 2013 (5 years, 7 months ago) by Ryan McConville
Tags: PhD

This was posted on Thu 15 Aug 2013 (5 years, 10 months ago) by Ryan McConville
This was posted on Tue 06 Aug 2013 (5 years, 10 months ago) by Ryan McConville
Hello, this is my first blog post!

I'm not sure how often I'll update this blog as I am just building this for fun and also as an opportunity to build more software with Python. Although I figured I should at least make a hello world post! :)
This was posted on Sat 23 Mar 2013 (6 years, 2 months ago) by Ryan McConville