Raspberry Pi: Setting up backup

I have a Raspberry Pi providing household automation and productivity services – WebDav, Backups and Calendar. I always worry about a jolt of power, a failed byte and something that is unrecoverable. Time for a Backup solution.

I plugged in a USB stick – 64GB, and immediately checked the file system is there and visible as SDA (unmounted).

pi@raspberrypi:~# sudo su - 

root@raspberrypi:~# lsblk 
 NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
 sda           8:0    1 58.2G  1 disk 
 └─sda1        8:1    1 58.2G  1 part 
 mmcblk0     179:0    0 14.9G  0 disk 
 ├─mmcblk0p1 179:1    0 43.9M  0 part /boot
 └─mmcblk0p2 179:2    0 14.8G  0 part /

I check to see which one is assigned to the SD card slot (mmc), I really don’t want to reformat Raspbian.  I see the USB stick is on /dev/sda. All of my subsequent commands use /dev/sda as part of the command.

root@raspberrypi:~# parted -ls
Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes.
 Model: JetFlash Transcend 64GB (scsi)
 Disk /dev/sda: 62.5GB
 Sector size (logical/physical): 512B/512B
 Partition Table: unknown
 Disk Flags: 

 Model: SD SC16G (sd/mmc)
 Disk /dev/mmcblk0: 15.9GB
 Sector size (logical/physical): 512B/512B
 Partition Table: msdos
 Disk Flags: 
 Number  Start   End     Size    Type     File system  Flags
  1      4194kB  50.2MB  46.0MB  primary  fat32        lba
  2      50.3MB  15.9GB  15.9GB  primary  ext4

If you don’t see the relevant information on your HD or run into issues formatting the hard-drive, install hdparm.  and check with hdparm -r0 /dev/sda  .

TIP: I did run into an issue with an ISO written to a USB drive which locks the partition table and makes it unwriteable.

root@raspberrypi:~# apt-get install hdparm
 Reading package lists… Done
 Building dependency tree       
 Reading state information… Done
 The following package was automatically installed and is no longer required:
   realpath
 Use 'apt autoremove' to remove it.
 The following additional packages will be installed:
   powermgmt-base
 Suggested packages:
   apmd
 The following NEW packages will be installed:
   hdparm powermgmt-base
 0 upgraded, 2 newly installed, 0 to remove and 148 not upgraded.
 Need to get 114 kB of archives.
 After this operation, 278 kB of additional disk space will be used.
 Do you want to continue? [Y/n] y
 Get:1 http://raspbian.mirror.constant.com/raspbian stretch/main armhf hdparm armhf 9.51+ds-1+deb9u1 [105 kB]
 Get:2 http://raspbian-us.ngc292.space/raspbian stretch/main armhf powermgmt-base all 1.31+nmu1 [9,240 B]
 Fetched 114 kB in 0s (120 kB/s)           
 Selecting previously unselected package hdparm.
 (Reading database … 135688 files and directories currently installed.)
 Preparing to unpack …/hdparm_9.51+ds-1+deb9u1_armhf.deb …
 Unpacking hdparm (9.51+ds-1+deb9u1) …
 Selecting previously unselected package powermgmt-base.
 Preparing to unpack …/powermgmt-base_1.31+nmu1_all.deb …
 Unpacking powermgmt-base (1.31+nmu1) …
 Setting up powermgmt-base (1.31+nmu1) …
 Setting up hdparm (9.51+ds-1+deb9u1) …
 Processing triggers for man-db (2.7.6.1-2) …
Preparing to unpack …/hdparm_9.51+ds-1+deb9u1_armhf.deb …

Unpacking hdparm (9.51+ds-1+deb9u1) …

Selecting previously unselected package powermgmt-base.

Preparing to unpack …/powermgmt-base_1.31+nmu1_all.deb …

Unpacking powermgmt-base (1.31+nmu1) …

Setting up powermgmt-base (1.31+nmu1) …

Setting up hdparm (9.51+ds-1+deb9u1) …

Processing triggers for man-db (2.7.6.1-2) …
root@raspberrypi:~# hdparm -r0 /dev/sda
 /dev/sda:
  setting readonly to 0 (off)
  readonly      =  0 (off)

Now that I know the drive is writeable, I need to create the partition. I used

cfdisk

Navigate through the menu and select the maximum size
                                                                                        Disk: /dev/sda
Size: 58.2 GiB, 62495129600 bytes, 122060800 sectors
Label: dos, identifier: 0x00000000

Device Boot Start End Sectors Size Id Type
>> /dev/sda1 2048 122060799 122058752 58.2G 83 Linux

Once you see “Syncing disks.”, you can format the disk. I formatted the partition sda1 with ext4 (I may want to encrypt in the future). Unmount and then format.

root@raspberrypi:~# umount /dev/sda1
root@raspberrypi:~# mkfs.ext4 /dev/sda1
mke2fs 1.43.4 (31-Jan-2017)
Found a dos partition table in /dev/sda1
Proceed anyway? (y,N) y
Creating filesystem with 2828032 4k blocks and 707136 inodes
Filesystem UUID: 363f1b4a-b0f5-4c7b-bf91-66f3823032d6
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

root@raspberrypi:~#

Make the backup directory, edit fstab and mount the directory.  Insert into fstab with your uuid “UUID=363f1b4a-b0f5-4c7b-bf91-66f3823032d6 /backups auto nosuid,nodev,nofail 0 0
”   The second to last avoids backup and the last one enables fsck on reboot.

root@raspberrypi:~# blkid 
/dev/mmcblk0p1: LABEL="boot" UUID="DDAB-3A15" TYPE="vfat" PARTUUID="b53687e8-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="5fa1ec37-3719-4b25-be14-1f7d29135a13" TYPE="ext4" PARTUUID="b53687e8-02"
/dev/mmcblk0: PTUUID="b53687e8" PTTYPE="dos"
/dev/sdb: UUID="363f1b4a-b0f5-4c7b-bf91-66f3823032d6" TYPE="ext4"
root@raspberrypi:~# mkdir /backups 
root@raspberrypi:~# vim /etc/fstab
root@raspberrypi:~# mount -a
root@raspberrypi:~# mount
UUID=363f1b4a-b0f5-4c7b-bf91-66f3823032d6 /backups auto nosuid,nodev,nofail 0 0


You should see backups listed. (Note: I bricked my Raspberry Pi with a bad FSTAB entry, and mounted it on my Mac using Paragon and removed the bad fstab entry. )

Update Crontab with daily backups.

crontab -e

Setup an editor for crontab.

root@raspberrypi:~# crontab -e
no crontab for root - using an empty one

Select an editor. To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano <---- easiest
3. /usr/bin/vim.basic
4. /usr/bin/vim.tiny

Choose 1-4 [2]: 3
crontab: installing new crontab

I added this line and copied it to /etc/cron.daily/

0 1 * * * /usr/bin/rsync -r /data/ /backups/`date +%w-%A`

crontab -l > pi-backup
mv /root/pi-backup /etc/cron.daily
run-parts /etc/cron.daily

Note, I had to add #!/bin/bash after I copied and remove the timing of the job.

Also, check to see if rsync is installed with which rsync and apt-get install rsync.

This enables backups on a daily basis rotating every 7 days.

Check back on the following day to see your backups

root@raspberrypi:~# /usr/bin/rsync -r /data/ /backups/`date +%w-%A`
root@raspberrypi:~# find /backups
/backups
/backups/lost+found
/backups/0-Sunday
/backups/0-Sunday/startup.sh

Good luck, I hope this helps you with your Raspberry Pi.

References

Java Micro Benchmarking Links

One of my colleagues mentioned Java MicroBenchmarking Harness (jmh), curiosity got the best of me, and I started playing with it for my project. Per a recommendation, I ran this as a new project. I created a new project using:
 mvn archetype:generate \
         -DinteractiveMode=false \
         -DarchetypeGroupId=org.openjdk.jmh \
         -DarchetypeArtifactId=jmh-
java-benchmark-archetype \
         -DgroupId=org.sample \
         -DartifactId=
test \
         -Dversion=1.0


https://javapapers.com/java/java-micro-benchmark-with-jmh/
https://openjdk.java.net/projects/code-tools/jmh/
https://www.baeldung.com/java-microbenchmark-harness
https://gist.github.com/nicoulaj/5517176
https://www.mkyong.com/java/java-jmh-benchmark-tutorial/
http://tutorials.jenkov.com/java-performance/jmh.html

Lessons Learned in July 2019

There is a Mojo in My Dojo (How to write a Maven plugin)

A handy website that outlines the creation of a maven plugin we used in a Java Healthcare project I was working on.   The Mojo I wrote used lessons learned in unit testing from the site.  Thank you to the author.

JAXP Debug Log

I am working on a Java healthcare project and needed to debug a JAXP model and how the serializers are loaded. This site outlined the use of the System property for -Djaxp.debug=1  to trigger debugging logs.

Zookeeper Port Forwarding to all servers from local machine

To simply testing with Zookeeper on a remote Kafka cluster, one must connect to the client application ports on the backend.  When the remote Kafka cluster has multiple nodes and behind a firewall and a SSH jump server, the complexity is fairly high.  Note, the SSH jump server is the permitted man in the middle. 
 
The client must allow application access to Zookeeper on Kafka – listening locally. Current techniques allow for a single port hosted on the developers machine for instance, 2181 listening on the local machine, and a single remote server.  This approach is not reliable – servers are taken out of service, added back, fail, or reroute to the master (another separate server).   
Port Description
88/tcp Kerberos
2181/tcp zookeeper.property.clientPort

A typical connection looks like: 

ssh -J jump-server kafka-1 -L 2181:kafka-1:2181 "while true; do echo "waiting"; sleep 180; done"
 
I worked to develop a small proxy. Setup hosts file.
1 – Edit /etc/hosts
2 – Add entry to hosts file
127.0.0.1 kafka-1

127.0.0.2 kafka-2

127.0.0.3 kafka-3

127.0.0.4 kafka-4

127.0.0.5 kafka-5
3 – Save the hosts file
4 – Setup Available interfaces (1 for each unique service)
1 is already up and in use (you only need to add the extras)
sudo ifconfig lo0 alias 127.0.0.2 up

sudo ifconfig lo0 alias 127.0.0.3 up

sudo ifconfig lo0 alias 127.0.0.4 up

sudo ifconfig lo0 alias 127.0.0.5 up
5 – Setup the port forwarding, forward to jump server ssh -L 30991:localhost:30991 jump-server
6 – Forward to Kafka server ssh -L 30991:localhost:2181 kafka-1
7 – Loop while on kafka server while true; do echo “waiting”; sleep 180; done
8 – Repeat for each kafka server increasing the port by 1 (refer to ports section for mapping)
9 – Setup the Terminal – node krb5-tcp.js
10 – Setup the Terminal – node proxy_socket.js

echo stats | nc kafka-1 2181
Zookeeper version: 3.4.6-IBM_4–1, built on 06/17/2016 01:58 GMT
Clients:
/192.168.12.47:50404[1](queued=0,recved=1340009,sent=1360508)
/192.168.12.46:48694[1](queued=0,recved=1348346,sent=1368936)
/192.168.12.48:39842[1](queued=0,recved=1341655,sent=1362178)
/0:0:0:0:0:0:0:1:39644[0](queued=0,recved=1,sent=0)

Latency min/avg/max: 0/0/2205
Received: 4878752
Sent: 4944171
Connections: 4
Outstanding: 0
Zxid: 0x1830001944e
Mode: follower
Node count: 442


11 – Use your code to access Zookeeper Server

References
https://github.com/nodejitsu/node-http-proxy
sudo ifconfig lo0 alias 127.0.0.6 up

sudo ifconfig lo0 alias 127.0.0.7 up

sudo ifconfig lo0 alias 127.0.0.8 up

Configuration

{

"2181": {

"type": "socket",

"members": [

{ "hostname": "kafka-1", "port": 30991 },

{ "hostname": "kafka-2", "port": 30992 },

{ "hostname": "kafka-3", "port": 30993 },

{ "hostname": "kafka-4", "port": 30994 },

{ "hostname": "kafka-5", "port": 30995 }

]

}

}

 

Jaas Configuration
./kerberos/src/main/java/demo/kerberos/jaas.conf
TestClient {
com.sun.security.auth.module.Krb5LoginModule required
principal="ctest4@test.COM"
debug=true
useKeyTab=true
storeKey=true
doNotPrompt=false
keyTab="/Users/paulbastide/tmp/kerberos/test.headless.keytab"
useTicketCache=false;
};

Java – App.java

package demo.kerberos;

import javax.security.auth.*;
import javax.security.auth.login.*;
import javax.security.auth.callback.*;
import javax.security.auth.kerberos.*;
import java.io.*;

public class App {
public static void main(String[] args) {

System.setProperty("java.security.auth.login.config",
"/Users/paulbastide/tmp/kerberos/src/main/java/demo/kerberos/jaas.conf");
System.setProperty("java.security.krb5.conf", "/Users/paulbastide/tmp/kerberos/krb5.conf");

Subject mysubject = new Subject();
LoginContext lc;

try {

lc = new LoginContext("TestClient", mysubject, new MyCallBackHandler());
lc.login();

} catch (LoginException e) {
e.printStackTrace();
}

}

}

Java - MyCallBackHandler.java
package demo.kerberos;

import javax.security.auth.*;
import javax.security.auth.login.*;
import javax.security.auth.callback.*;
import javax.security.auth.kerberos.*;
import java.io.*;

public class MyCallBackHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {

for (int i = 0; i < callbacks.length; i++) {
System.out.println(callbacks[i]);
}
}
}
 

VirtualBox Installation Issue – Code Signer

While installing virtualbox, I ran into this issue https://stackoverflow.com/questions/55004803/install-virtualbox-6-on-mac-10-14-mojave-failed-with-kernel-install-error

Net: the Oracle/VirtualBox ID is NOT in the approved keys/certs.

I did not follow the exact steps.

  1. Launch Terminal
  2. sudo -s
  3. Enter password for the user to switch
  4. spctl kext-consent –disable
  5. Install VirtualBox
  6. spctl kext-consent –enable

At the end of the steps, I was able to launch VirtualBox. I did not have to reboot.

License Management via Maven Plugin

Keeping a license current is luckily addressed by the mycila license maven plugin. This plugin scans the project files in src files and updates the files with the license.txt format. To configure the plguin refer to http://code.mycila.com/license-maven-plugin/reports/3.0/format-mojo.html#excludes.

To check the current status of the copyrights and see what needs to be updated: mvn com.mycila:license-maven-plugin:check -f my-parent/pom.xml

To format the current missing copyrights and update: mvn com.mycila:license-maven-plugin:format -f my-parent/pom.xml

Results are:
[INFO] ————————————————————————
[INFO] Building my-project 99-SNAPSHOT
[INFO] ————————————————————————
[INFO]
[INFO] — license-maven-plugin:3.0:format (default-cli) @ my-project —
[INFO] Updating license headers…
[WARNING] Unknown file extension: /Users/paulbastide/git/wffh/my/my-project/.factorypath
[INFO] Updating license header in: /Users/paulbastide/git/wffh/my/my-project/src/main/webapp/WEB-INF/ibm-web-ext.xml
[WARNING] Unable to find a comment style definition for some files. You may want to add a custom mapping for the relevant file extensions.
[INFO]
 
Once you run the copyright format, you’ll see the change in the files.

Plugin for your pom.xml
The plugin snippet as follows and that goes in <build><plugins></plugins></build>:
 
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<configuration>
<properties>
<year>2019</year>
</properties>
<excludes>
<exclude>src/test/**</exclude>
<exclude>src/main/resources/**</exclude>
<exclude>liberty-config/**</exclude>
<exclude>docker/**</exclude>
</excludes>
<failIfMissing>false</failIfMissing>
<skipExistingHeaders>true</skipExistingHeaders>
<header>license.txt</header>
</configuration>
</plugin>

To run the mojo independently use:
mvn com.mycila:license-maven-plugin:check -f my-project/pom.xml -Dlicense.header=./license.txt -license.skipExistingHeaders=true

Maven Dependency Version Management

To check the version of a dependency (and subsequently all dependencies), and see if there is a need to update the dependency:

1 - Change to cd my-project
2 - Run mvn versions:display-dependency-updates
3 - Locate the section in the output:
[INFO] The following dependencies in Dependency Management have newer versions:
[INFO] com.cloudant:cloudant-client ......................... 2.4.1 -> 2.16.0

4 – For each of the entries, update the core dependency to the latest version on the right.

08:57:36-mymachine:~/git/my-project$ mvn versions:display-dependency-updates
[INFO] Scanning for projects...
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/plugins/maven-failsafe-plugin/2.20.1/maven-failsafe-plugin-2.20.1.pom
...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building my-project 99-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- versions-maven-plugin:2.3:display-dependency-updates (default-cli) @ my-project ---
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-provider-api/2.5/wagon-provider-api-2.5.pom
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-provider-api/2.5/wagon-provider-api-2.5.pom (2 KB at 0.8 KB/sec)
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon/2.5/wagon-2.5.pom
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon/2.5/wagon-2.5.pom (20 KB at 8.7 KB/sec)
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-file/2.5/wagon-file-2.5.pom
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-file/2.5/wagon-file-2.5.pom (2 KB at 0.8 KB/sec)
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-providers/2.5/wagon-providers-2.5.pom
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-providers/2.5/wagon-providers-2.5.pom (3 KB at 1.3 KB/sec)
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-provider-api/2.5/wagon-provider-api-2.5.jar
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-file/2.5/wagon-file-2.5.jar
Downloading: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/doxia/doxia-core/1.4/doxia-core-1.4.jar
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-provider-api/2.5/wagon-provider-api-2.5.jar (52 KB at 24.4 KB/sec)
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/wagon/wagon-file/2.5/wagon-file-2.5.jar (11 KB at 4.9 KB/sec)
Downloaded: https://repo1.maven.org/nexus/wh/content/groups/public/org/apache/maven/doxia/doxia-core/1.4/doxia-core-1.4.jar (162 KB at 69.5 KB/sec)
[INFO] artifact com.google.collections:google-collections: checking for updates from public
[INFO] artifact com.google.code.gson:gson: checking for updates from public
[INFO] artifact com.cloudant:cloudant-client: checking for updates from public
[INFO] artifact com.googlecode.json-simple:json-simple: checking for updates from public
[INFO] artifact com.ibm.db2:db2jcc4: checking for updates from public
[INFO] artifact com.ibm.websphere.appserver.runtime:wlp-base-embeddable: checking for updates from public
[INFO] artifact com.ibm.java:ibm-java-sdk: checking for updates from public
[INFO] artifact com.ibm.whc:audittrail-retrieve-api: checking for updates from public
[INFO] artifact commons-beanutils:commons-beanutils: checking for updates from public
[INFO] artifact commons-cli:commons-cli: checking for updates from public
[INFO] artifact commons-codec:commons-codec: checking for updates from public
[INFO] artifact commons-io:commons-io: checking for updates from public
[INFO] artifact javax.json:javax.json-api: checking for updates from public
[INFO] artifact javax.mail:mail: checking for updates from public
[INFO] artifact javax.servlet:javax.servlet-api: checking for updates from public
[INFO] artifact javax.transaction:javax.transaction-api: checking for updates from public
[INFO] artifact javax.websocket:javax.websocket-api: checking for updates from public
[INFO] artifact javax.ws.rs:javax.ws.rs-api: checking for updates from public
[INFO] artifact junit:junit: checking for updates from public
[INFO] artifact net.sf.saxon:Saxon-HE: checking for updates from public
[INFO] artifact net.wasdev.maven.tools.targets:liberty-target: checking for updates from public
[INFO] artifact org.apache.cxf:cxf-rt-frontend-jaxrs: checking for updates from public
[INFO] artifact org.apache.cxf:cxf-rt-rs-client: checking for updates from public
[INFO] artifact org.apache.derby:derby: checking for updates from public
[INFO] artifact org.apache.derby:derbyclient: checking for updates from public
[INFO] artifact org.apache.derby:derbynet: checking for updates from public
[INFO] artifact org.apache.derby:derbytools: checking for updates from public
[INFO] artifact org.apache.httpcomponents:httpclient: checking for updates from public
[INFO] artifact org.apache.httpcomponents:httpcore: checking for updates from public
[INFO] artifact org.apache.kafka:kafka-clients: checking for updates from public
[INFO] artifact org.eclipse.persistence:org.eclipse.persistence.moxy: checking for updates from public
[INFO] artifact org.glassfish:javax.json: checking for updates from public
[INFO] artifact org.glassfish.tyrus.bundles:tyrus-standalone-client-jdk: checking for updates from public
[INFO] artifact org.json:json: checking for updates from public
[INFO] artifact org.liquibase:liquibase-core: checking for updates from public
[INFO] artifact org.mockito:mockito-core: checking for updates from public
[INFO] artifact org.owasp.encoder:encoder: checking for updates from public
[INFO] artifact org.skyscreamer:jsonassert: checking for updates from public
[INFO] artifact org.testng:testng: checking for updates from public
[INFO] artifact xmlunit:xmlunit: checking for updates from public
[INFO] The following dependencies in Dependency Management have newer versions:
[INFO] com.cloudant:cloudant-client ......................... 2.4.1 -> 2.16.0
[INFO] com.google.code.gson:gson ............................. 2.8.1 -> 2.8.5
[INFO] com.googlecode.json-simple:json-simple .................. 1.1 -> 1.1.1
[INFO] com.ibm.java:ibm-java-sdk .......... 8.0-5.35-linux-x86_64 -> 8.0.2.10
[INFO] commons-codec:commons-codec ............................. 1.10 -> 1.12
[INFO] commons-io:commons-io ..................................... 2.4 -> 2.6
[INFO] org.testng:testng .............................. 6.9.10 -> 7.0.0-beta4
[INFO]
[INFO] No dependencies in Dependencies have newer versions.
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:39 min
[INFO] Finished at: 2019-05-21T09:03:55-04:00
[INFO] Final Memory: 15M/182M
[INFO] ------------------------------------------------------------------------

Reference

https://stackoverflow.com/questions/2687220/maven-check-for-updated-dependencies-in-repository

Two New Power User Hacks

https://serverfault.com/questions/283129/why-do-consoles-sometimes-hang-forever-when-ssh-connection-breaks
~. – terminate connection (and any multiplexed sessions)
~B – send a BREAK to the remote system
~C – open a command line
~R – request rekey
~V/v – decrease/increase verbosity (LogLevel)
~^Z – suspend ssh
~# – list forwarded connections
~& – background ssh (when waiting for connections to terminate)
~? – this message
~~ – send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

Tip #2. The other a really handy technique to regain control of my system. The Kernel was hung something severe, turned out to be a problem with the network storage. I ran the magic key for Immediately reboot the system, without unmounting or syncing filesystems 

https://major.io/2009/01/29/linux-emergency-reboot-or-shutdown-with-magic-commands/ 

https://en.wikipedia.org/wiki/Magic_SysRq_key

Cups and Raspberry Pi – How to setup your print server

Print Server is one of those things that makes life easier.  I hooked up my Raspberry Pi and a Docker image in order to have a CUPS server and the Bonjour configuration.

Login to the Raspberry Pi and switch to root (sudo -s or sudo su –)

Check lsusb to see if you can see the USB device.

 root@raspberrypi:~# lsusb 
Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 004: ID 8564:1000 Transcend Information, Inc. JetFlash
Bus 001 Device 006: ID 0424:7800 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
root@raspberryp:~#

If you don’t see it, check to see that the device is properly plugged in.

Check again, and you’ll see your manufacture for your printer listed. (highlighted in red)

 root@raspberrypi:~# lsusb 
Bus 001 Device 007: ID 03f0:7411 Hewlett-Packard
Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 004: ID 8564:1000 Transcend Information, Inc. JetFlash
Bus 001 Device 006: ID 0424:7800 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
root@raspberrypi:~#

Further, I am able to see the exact model that is connected:

 root@raspberrypi:~# lsusb -v | grep -A 20 Hewlett-Packard 
Bus 001 Device 007: ID 03f0:7411 Hewlett-Packard
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x03f0 Hewlett-Packard
  idProduct          0x7411
  bcdDevice            1.00
  iManufacturer           1 HP
  iProduct                2 Photosmart C4600 series
  iSerial                 3 |||MASKED|||MASKED|||MASKED|||

I’ll use these details downstream in order to install and use the HP driver.

If you still don’t see the USB device, you should check dmesg and look at the pattern for USB.

 [3077006.701281] usb 1-1.2: new high-speed USB device number 7 using dwc_otg
[3077006.831891] usb 1-1.2: New USB device found, idVendor=03f0, idProduct=7411
[3077006.831908] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[3077006.831917] usb 1-1.2: Product: Photosmart C4600 series
[3077006.831925] usb 1-1.2: Manufacturer: HP

If you don’t see it, unplug and plug the device back in.

You can also use usb-devices

 T:  Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#=  7 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=03f0 ProdID=7411 Rev=01.00
S:  Manufacturer=HP
S:  Product=Photosmart C4600 series
S:  SerialNumber=<<>><<>>
C:  #Ifs= 4 Cfg#= 1 Atr=c0 MxPwr=2mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=cc Prot=00 Driver=(none)
I:  If#= 1 Alt= 0 #EPs= 2 Cls=07(print) Sub=01 Prot=02 Driver=usblp
I:  If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
I:  If#= 3 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage

Copy the Dockerfile and the cupsd file locally (in the folder etc-cups/cupsd.conf). Cupsd is configured to listen on all interfaces: Listen 0.0.0.0:631

Build the Docker image (based off of this image https://github.com/a0js/rpi-cups and uses a different base image https://hub.docker.com/r/arm32v7/debian/ ) docker build -t cups-pi/cups-pi .

 root@raspberrypi:/data/cups-printer# docker build -t cups-pi/cups-pi . 
Sending build context to Docker daemon  8.192kB
Step 1/9 : FROM arm32v7/debian:latest
 ---> 64b4748d266b
Step 2/9 : ENV DEBIAN_FRONTEND noninteractive
 ---> Using cache
 ---> 38ebdf2f5bb6
Step 3/9 : RUN apt-get update && apt-get install -y   sudo   locales   whois   cups   cups-client   cups-bsd   printer-driver-all   hpijs-ppds   hp-ppd   hplip
 ---> Using cache
 ---> 0b5b9eac6cef
Step 4/9 : RUN sed -i "s/^#\ \+\(en_US.UTF-8\)/\1/" /etc/locale.gen && locale-gen en_US en_US.UTF-8
 ---> Using cache
 ---> fd55737901b8
Step 5/9 : ENV LANG=en_US.UTF-8   LC_ALL=en_US.UTF-8   LANGUAGE=en_US:en
 ---> Using cache
 ---> d6cd104b40ec
Step 6/9 : RUN useradd   --groups=sudo,lp,lpadmin   --create-home   --home-dir=/home/print   --shell=/bin/bash   --password=$(mkpasswd print)   print   && sed -i '/%sudo[[:space:]]/ s/ALL[[:space:]]*$/NOPASSWD:ALL/' /etc/sudoers   && apt-get clean   && rm -rf /var/lib/apt/lists/*   && mkdir /var/lib/apt/lists/partial
 ---> Using cache
 ---> 156dcd02e397
Step 7/9 : COPY etc-cups/cupsd.conf /etc/cups/cupsd.conf
 ---> e1624a96970e
Step 8/9 : EXPOSE 631
 ---> Running in a16705e0f3d9
Removing intermediate container a16705e0f3d9
 ---> 60758af63011
Step 9/9 : ENTRYPOINT ["/usr/sbin/cupsd", "-f"]
 ---> Running in add02d421ea9
Removing intermediate container add02d421ea9
 ---> 8c6fe42423c8
Successfully built 8c6fe42423c8
Successfully tagged cups-pi/cups-pi:ltest

Run the Docker image to start the print server

root@raspberrypi:/data/cups-printer# docker run -d -p 631:631 --privileged -v /var/run/dbus:/var/run/dbus -v /dev/bus/usb:/dev/bus/usb -h myhostm.mydomain.org --name cupsm cups-pi/cups-pi:latest
fe6d9bc34c66911f05b011ef185fce95947efb965e90ef2b4ecdd0f1c3a32d68

It’s important to use the -h if you want to remotely access via hostname.

Login to the console http://myserver.mydomain.org:631/admin using print:print

Click Add Printer

Select a local printer “HP Photosmart C4600 series (HP Photosmart C4600 series)”

Click Continue

Click Share This Printer

Click Continue

Click Add Printer

Select Media Type – Letter

Click Set Default Options

Click Add

When you find the Printer, you can add the printer

You now have an image ready for use with a CUPS printer.  (If you rebuild, you may have to re-setup the default printer…. Just warning you ahead of time).  You can always look at http://myhost.mydomain.org:631/printers/HP_Photosmart_C4600_series

If you need to connect to the console, you can look at the docker ps

root@raspberrypi:/data/cups-printer# docker ps
CONTAINER ID        IMAGE                    COMMAND                CREATED             STATUS              PORTS                                    NAMES
fe6d9bc34c66        cups-pi/cups-pi:latest   "/usr/sbin/cupsd -f"   5 minutes ago       Up 5 minutes        0.0.0.0:631->631/tcp                     cups

Extract the CONTAINER ID, and look at the /bin/sh

root@raspberrypi:/data/cups-printer# docker exec
-i -t fe6d9bc34c66 /bin/sh

Then look at the /var/log/cups files, specifically the error_log

Reference

List USB Devices Linux https://linuxhint.com/list-usb-devices-linux/

Dockerfile https://github.com/a0js/rpi-cups https://github.com/ryansch/docker-cups-rpi https://github.com/aadl/docker-cups/blob/master/2.2.1/Dockerfile

Arm 7 https://hub.docker.com/r/arm32v7/debian/

Cupsd.conf https://raw.githubusercontent.com/a0js/rpi-cups/master/etc-cups/cupsd.conf https://wiki.archlinux.org/index.php/CUPS/Printer_sharing

SSL / Advanced Configuration http://chschneider.eu/linux/server/cups.shtml http://192.168.86.176:631/admin (use IP if receiving a bad request indicator to the admin interface)

Advanced Ubuntu Configuration https://help.ubuntu.com/lts/serverguide/cups.html.en