MacBook Ubuntu Overheating

I dual boot Ubuntu 14.04 LTS on my work MacBook Pro (2015?). The SSD makes it a pretty quick dev machine but out of the box temperature control doesn’t seem to work. There are lots of outdated old forum posts about manually setting the fan speed. In 2018 all you need to do get fan control working is install macfanctld!

$ sudo apt install lm-sensors
$ sensors
BAT0-virtual-0
Adapter: Virtual device
temp1: +35.3°C

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0: +73.0°C (high = +84.0°C, crit = +100.0°C)
Core 0: +73.0°C (high = +84.0°C, crit = +100.0°C)
Core 1: +69.0°C (high = +84.0°C, crit = +100.0°C)
Core 2: +71.0°C (high = +84.0°C, crit = +100.0°C)
Core 3: +68.0°C (high = +84.0°C, crit = +100.0°C)
...

Install fan control daemon:

sudo apt install macfanctld

Instantly the fans spin up and the temperature quickly drops down to normal:

$ sensors
BAT0-virtual-0
Adapter: Virtual device
temp1: +33.9°C

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0: +54.0°C (high = +84.0°C, crit = +100.0°C)
Core 0: +54.0°C (high = +84.0°C, crit = +100.0°C)
Core 1: +50.0°C (high = +84.0°C, crit = +100.0°C)
Core 2: +50.0°C (high = +84.0°C, crit = +100.0°C)
Core 3: +50.0°C (high = +84.0°C, crit = +100.0°C)
...
Advertisements

Remote Torrent Server with Deluge Web & Systemd

The Deluge torrent client can be run headless which is useful for downloading on a remote media server.

Install deluge & deluge-web

sudo apt install deluge deluged deluge-web

Systemd Services

/etc/systemd/system/deluged.service

[Unit]
Description=Deluge Torrent Server

[Service]
Type=simple
User=austin
Environment=
WorkingDirectory=/home/austin/
ExecStart=/usr/bin/deluged --do-not-daemonize
Restart=always

[Install]
WantedBy=multi-user.target

/etc/systemd/system/delugeweb.service

[Unit]
Description=Deluge Torrent Server

[Service]
Type=simple
User=austin
Environment=
WorkingDirectory=/home/austin/
ExecStart=/usr/bin/deluge-web
Restart=always

[Install]
WantedBy=multi-user.target

Starting the Services

sudo systemctl enable deluged.service
sudo systemctl start deluged.service
sudo systemctl enable delugeweb.service
sudo systemctl start delugeweb.service

Using Deluge Web UI

Open the web client:

http://MY_SERVER_IP:8112

The default password is ‘deluge’

Auto-connect of Web UI to Daemon

Modify ~/.config/deluge/web.conf and set “default_daemon” to the hash found in ~/.config/deluge/hostlist.conf.1.2

I assume you need to manually connect once to populate hostlist.

 

Media Server for Chromecast Streaming

I have now switched to using a Chromecast for all our TV needs. I have an old Android phone (Moto G) that has been re-purposed as the remote. For local pre-downloaded content, I have a Media Server running Ubuntu 17.10. The best setup I have found for streaming this local content to the Chromecast is VideoStream.

 

VideoStream Install

The Android App can be found here: https://getvideostream.com/
On Linux, there is no native install so you need to use Chrome and install VideoStream as an extension: https://chrome.google.com/webstore/detail/videostream-for-google-ch/cnciopoikihiagdjbjpnocolokfelagl?hl=en

As my server is headless, the install of Chrome and the VideoStream extension are done using ssh -X.

When you Pair your device, you also need to have Chrome open over SSH to receive the popup and accept the pairing.

Running VideoStream Headless on Boot

Create the following systemd service file: /etc/systemd/system/videostream.service

[Unit]
Description=VideoStream Server

[Service]
User=austin
Environment=
WorkingDirectory=/home/austin/
ExecStart=/bin/bash xvfb-run google-chrome --app-id=cnciopoikihiagdjbjpnocolokfelagl
Restart=always

[Install]
WantedBy=multi-user.target

Streaming Apps

Netflix, TVNZ and TV3.

Automated backup of an external drive on Linux

The following steps set up a backup for a particular USB drive every time it is inserted. Very useful for avoiding the perils of working directly from a flash drive on multiple computers.
 

Create the backup script that uses duplicity:

/usr/local/bin/usb_drive_backup.sh

#!/bin/bash

DRIVE_NAME=USBDRIVE
BACKUP_DIR=/home/username/BACKUPS/USBDriveBackup

sleep 4

duplicity incremental /media/username/USBDRIVE file://$BACKUP_DIR --no-encryption >> $BACKUP_DIR/log.txt
if [ $? -eq 0 ]; then
    echo "## Backup complete `date`" >> $BACKUP_DIR/log.txt
    echo
fi

/usr/local/bin/usb-backup-in_udev

#!/bin/bash

/usr/local/bin/usb_drive_backup.sh &

 
 
Set up the udev rule to run the backup script every time the drive is inserted:

Find the device ID

$ lsusb
Bus 002 Device 002: ID 0930:1400 Toshiba Corp. Memory Stick 2GB
...

/etc/udev/rules.d/00-usb-backup.rules

ACTION=="add", ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1400", ENV{XAUTHORITY}="/home/username/.Xauthority", ENV{DISPLAY}=":0", OWNER="username", RUN+="/usr/local/bin/usb-backup-in_udev"

 
 
Restoring the backup:

duplicity restore file:///home/username/BACKUPS/USBDriveBackup ./RestoredFiles/ --no-encryption

Bash – Loops using pipe and read

Perform some operation for every line in the output of a command, e.g. add .txt to every file in a directory:

ls /var/* | while read fname; do cp $fname $fname.txt; done

Instead of:

for fname in `ls /var/*`; do cp $fname $fname.txt; done

Neat trick I actually picked up in a job interview. Easier to read if the original command is long as it avoids the backticks, and bash is all about readability, right?? 🙂

Bash String Manipulation

Bash has some convenient string manipulation functions. I often use substring removal which is very handy for trimming suffixes and prefixes from things like file names. These operations all evaluate to a new string and don’t modify the original variable.

Suffix removal
Remove the longest match from end:
    output=${string%%suffix}
Remove the shortest match from end:
    output=${string%suffix}

Prefix removal
Remove the longest match from front:
    output=${string##prefix}
Remove the shortest match from front:
    output=${string#prefix}

Great reference for more string operations: http://tldp.org/LDP/abs/html/string-manipulation.html

VirtualBox driver (vboxdrv) missing after Ubuntu 12.04 upgrade

After upgrading to 12.04 I got the following error when trying to start VirtualBox:

The VirtualBox Linux kernel driver (vboxdrv) is either not loaded or there is a permission problem with /dev/vboxdrv. Please reinstall the kernel module by executing

‘/etc/init.d/vboxdrv setup’

as root. If it is available in your distribution, you should install the DKMS package first. This package keeps track of Linux kernel changes and recompiles the vboxdrv kernel module if necessary.

The script mentioned did not exist because the vboxdrv was not compiled.
# sudo /etc/init.d/vboxdrv setup
sudo: /etc/init.d/vboxdrv: command not found

If you reinstall virtualbox-dkms it will recompile the driver for your kernel version, provided you have the correct kernel headers.
# sudo apt-get remove dkms virtualbox-dkms
# uname -a
Linux pc786-ubu 3.2.0-33-generic #52-Ubuntu SMP Thu Oct 18 16:29:15 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
# sudo apt-get install linux-headers-3.2.0-33
# sudo apt-get install dkms virtualbox-dkms

Receiving raw packets in Linux without pcap

Since there was a lot of interest in my post on sending raw Ethernet packets, this is an example of receiving packets on a raw socket. A compiling version can be found on github: https://gist.github.com/2862515. The application that I developed this for was to receive packets sent to a specific MAC address. The main sections are explained below:

Open raw socket listening for ETHER_TYPE

	if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
		perror("listener: socket");	
		return -1;
	}

Set interface to promiscuous mode

	strncpy(ifopts.ifr_name, ifName, IFNAMSIZ-1);
	ioctl(sockfd, SIOCGIFFLAGS, &ifopts);
	ifopts.ifr_flags |= IFF_PROMISC;
	ioctl(sockfd, SIOCSIFFLAGS, &ifopts);

Allow socket to be reused

	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
		perror("setsockopt");
		close(sockfd);
		exit(EXIT_FAILURE);
	}

Bind to device

	if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, IFNAMSIZ-1) == -1)	{
		perror("SO_BINDTODEVICE");
		close(sockfd);
		exit(EXIT_FAILURE);
	}

Receive on socket

	numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL);
	printf("listener: got packet %lu bytes\n", numbytes);

Print the data

	printf("\tData:");
	for (i=0; i<numbytes; i++) printf("%02x:", buf[i]);
	printf("\n");

Close socket

	close(sockfd);