All posts by ephestione

Sync OneDrive and Dropbox to more than 3 total devices

Disclaimer: this will be wonky, probably you will not like it, but it’s free, so what do you have to lose.

Facts: Dropbox and OneDrive are both free; Dropbox allows only up to 3 paired devices at all times (no idea about OneDrive).

Let’s say you want to let a fourth device access Dropbox for free, at least (or even better yet) for just a subset of files in your dropbox.

Enter OneDrive.

Install and configure it, then make use of Windows mklink command to create symlinks, by opening an elevated command prompt from the start menu (open start menu, type “cmd” and right click on the command prompt link, choosing “Run as administrator”), then cd into OneDrive’s root folder, and type:

mklink /D things path\to\Dropbox\folder\you_want_to_share

from now on, OneDrive will start uploading the contents of the Dropbox folder you specified, so they will be available to your other PCs’ OneDrive installations past the limit of 3 concurrent devices.

I tested that an empty text file created in the 4th PC’s OneDrive folder will appear in the Dropbox+OneDrive PC’s Dropbox folder, but I noticed that edits of this empty file don’t really propagate… maybe it’s just a matter of time? Also, deleting that file in the Dropbox+OneDrive PC will not delete the file in the 4th OneDrive only PC.

This is just from a few minutes of testing, I wanted to share the news.

Fix crontabS fdopen Permission denied

Somehow my Raspberry started giving me this error whenever I tried crontab -e from a user account (sudo crontab -e worked fine for root contab, or sudo crontab -e -u username for offending user).

I searched on the internet several times, trying to fix permissions on crontabs folder, without any joy, until this post finally helped me:

sudo chown root:crontab /usr/bin/crontab
sudo chmod 2755 /usr/bin/crontab

and I was able to edit user’s crontab from user’s CLI.

Boot Btrfs root partition with Raid1 on Raspberri Pi

This article stems from two different sources:

https://feldspaten.org/2019/07/05/raspbian-and-btrfs/

and

https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=319427

and I decided to summarize the process here, after extensively testing on a Raspberry Pi 4 with 8GB of RAM, and a 64bit OS; I might extend this guide to include setting up a Raid1 with a second disk (spoiler: I already did, down at the end of this page).

WARNING
I suggest testing this procedure on a pendrive where you flashed the image of a raspberry pi os distribution, WITHOUT using apt update & full-upgrade for two reasons:

  1. nothing bad will happen if things go wrong, since it’s not a production environment
  2. you’ll be able to test the kernel update automation AFTER you completed all the steps, by running the apt update && full-upgrade commands

Install requirements and edit needed modules:

sudo apt install initramfs-tools btrfs-tools
sudo nano /etc/initramfs-tools/modules

Add the following lines to the file and save:

btrfs
xor
zlib_deflate
raid6_pq

Create the initramfs in /boot partition and edit config.txt:

sudo mkinitramfs -o /boot/initramfs-btrfs.gz
sudo nano /boot/config.txt

adding the following line up top and save:

# For more options and informations see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

initramfs initramfs-btrfs.gz

For good measure, check if rebooting the system is succesful. Then sudo poweroff and place the disk (SD, SSD, pendrive) on a linux PC (or just reboot the same Raspberry Pi with a different media you prepared, like an SD card or a pendrive, leaving the disk attached) , and, let’s say the device is recognized as /dev/sdb:

sudo fsck.ext4 /dev/sdb2
sudo btrfs-convert /dev/sdb2                 
sudo mkdir /mnt/rootfs
sudo mount /dev/sdb2 /mnt/rootfs

We’ve just checked if the existing ext4 rootfs is clean, then we converted it to btrfs (it will take quite some time to create the ext2 image to make rollback possible), then created a mountpoint and mounted to it the just converted btrfs root partition.

We now need to update the fstab in this partition so the system will correctly mount at boot:

sudo nano /mnt/rootfs/etc/fstab

Correct the root line (/) by replacing ext4 with btrfs, and make it sure it ends with two 0‘s to disable fsck on it (btrfs has its own builtin filesystem checks, and fsck might return unwarranted errors).

Also, correct /boot/cmdline.txt in the boot partition by replacing, again, ext4 with btrfs, and fsck.repair=yes with fsck.repair=no.

At this point, placing the drive back on the Pi (or removing the other booting media and leaving just the disk) and booting will take you in a btrfs rootfs.

BEWARE navigators: this was my major gripe, as without anything else added to the procedure, a kernel update will be followed by a useless system at the next reboot, because the initramfs won’t be recreated.

User dickon on raspberrypi forums was a great help in the following procedure.

You need to create a script to automatically update initramfs in /boot after a kernel update, so here it is.

sudo nano /etc/kernel/postinst.d/btrfs-update

Insert this code in the script (this will work with a 64bit OS, make sure kernel8.img is the correct filename, you can check against the existing file in /boot, otherwise change accordingly):

#!/bin/bash
if [ "x$2" != "x/boot/kernel8.img" ]; then
	exit 0
fi

echo ============ UPDATE INITRAMFS ==============
mkinitramfs -o /boot/initramfs-btrfs.gz 0,86 EUR
echo ============ UPDATE COMPLETED ==============

then make sure it is executable, and has the same permissions of the other files in the same folder:

sudo chmod 755 /etc/kernel/postinst.d/btrfs-update

At this point, the system will (should) update the relevant initramfs right after each kernel update, freeing you of the hassle of remembering to do it by hand, or risk having a useless system after the next reboot.

It is a good idea to disable swap, since btrfs won’t be able to host a swap file anyway:

sudo systemctl disable dphys-swapfile.service

or alternatively, for a more aggressive approach that will remove the swapfile capabilities entirely:

sudo dphys-swapfile swapoff
sudo dphys-swapfile uninstall
sudo update-rc.d dphys-swapfile remove
sudo apt purge dphys-swapfile

In case you have a spare SSD lying around (who doesn’t) and you want to leverage the advantages of both redundancy and concurrent read speeds, then you can easily use btrfs innate capabilities for this.

You should mirror the partitioning of the system disk on the second SSD (unless there is a large disparity in size), and when that’s done, like detailed here, follow these steps:

sudo btrfs filesystem show

will confirm that the partition assigned to the rootfs mountpoint is the one you just converted a while ago. Let’s assume the partition you want to mirror the rootfs to is /dev/sdb1:

sudo btrfs device add -f /dev/sdb1 /

will assign it to the rootfs mountpoint, which you can confirm by re-issuing:


sudo btrfs filesystem show

that will show the second drive together with the first; you will then instruct btrfs to proceed with the actual mirroring of the data:

sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 /

which might take some time depending on the amount of used space on the partition.

From now on, you will be able to add even more drives, or remove failing ones to substitute them, and there is plenty of resources online that you can search for without me having to detail them all in here.

HOCl Hypochlorous Acid using salt water electrolysis

 

I have published several videos on youtube about HOCl production, the older one, the newer one, and the italian one, even older and uglier. Yet another might be in the works, as the vat model I’m currently using is different from the one in the latest video, and I plan to build another improved version of that.

Anyway, I’m creating this post because one user on youtube made several very interesting questions that deserve to be answered here as well.

chrastitko asked:

I am really confused after many days of research of this topic. I have really doubt if it is possible to get HoCl by simple electolysis of NaCl, but on the other hand does the USA companies lies about theyre commercial products? Or it is really so important to keep very specific conditions (size of electrodes, voltage, amperage, etc.) I have made many of attempts with concentration of salt vinegar, duration of electrolysis. I haven’t got enough big electrodes (now ordered from aliexpress similar as yours) and I haven’t got ppm tester so I can’t evalueate the final product. When I used a small amount of salt and vinegar and let electrolysis almost 2 hour (because of weak power supply, small electrodes 1 lite of solution) it doesn’t smell so intensive by chlorine like before when I used much salt. But if I tried to immerse cloth to this solution it bleaches it a little. So I am not sure if it should be HoCl or not. HoCl should smell so strong like NaOCl or not? It is the right technique to rise the time of electrolysis when you have small electrodes? What happens to solution if you let it run too long?

To which I replied:

you pose good questions. I am not the guy for you as I can only answer by experience, not by knowledge. My solution has not showed to bleach tissues, given I have never submerged a cloth inside it, but I spray many dressed people all day long when they access a certain area, been doing it for a year, and noone complained yet. The best way I can describe the smell of my solution after it’s been for a few hours inside the reservoir of the pressure painter I use to spray it, is “swimming pool changing room”, if you know what I mean. The concentration of HOCl in the final solution is a result of: pH of the solution (optimal is 5 if I remember correctly, yet 6 is pretty much the same), amount of electrical current (which itself is proportional to voltage, electrodes area, electrodes distance, and amount of electrolytes in the solution, that is, salt), and amount of salt (so how much salt you place in there will speed up the reaction twice, but will also leave a larger salt residue when the solution dries up). By the way, regarding the evidence that this method really works, there’s plenty of papers where it’s detailed that electrolysis is the simplest way to obtain HOCl, albeit not the most efficient. Running the electrolysis for too long will warm up the solution because of Joule effect (possibly degrading the HOCl which is in itself unstable), and increase the amount of corrosion the anode will go through.

 

Convertire automaticamente da FLAC a MP3

Scrivo per riferimento personale questa guida, che traggo da un post semplice ed efficace, e che per utilità generale traduco in italiano e inserisco nel mio blog a scopo di “backup”.

I file FLAC sono lossless, cioè fedeli alla qualità del CD originale. Ma l’orecchio umano non è perfetto, quindi fatto salvo tu sia un audiofilo investito di poteri extrasensoriali, la conversione a MP3 ti darà la stessa medesima qualità percepita ad una frazione dello spazio occupato.

Per questo, da Linux, o da Ubuntu installato su Windows 10 tramite WSL (qui una guida), installare i codec LAME e FLAC con:

sudo apt install lame flac


E quindi dopo essersi spostati nella cartella contenente i file FLAC che si desidera convertire (su Ubuntu sotto WSL, il percorso è /mnt/<lettera drive>/percorso/della/cartella), eseguire il comando:

for f in .flac; do flac -cd "$f" | lame -b 320 - "${f%.}".mp3; done


che per ogni file FLAC presente, crea una versione MP3 a bitrate costante di 320kbps. Potete cambiare il numero da 320 a un valore inferiore per ridurre il bitrate, o sostituire l’intero blocco -b 320 con -v, per un bitrate variabile, ma se lo fate siete degli zotici e non meritate di ascoltare musica.

Scherzo dai.

Dritte per un decoupage di fumetti su tavolo

Questo articolo è tanto divulgativo quanto di riferimento personale, infatti dopo le fatiche affrontate durante un progettino in corso d’opera ho pensato che sarebbe meglio metter nero su bianco quello che ho imparato.

In ordine più o meno sparso:

  • superficie più pulita possibile, se si tratta di legno appena levigato accertarsi che sia stata rimossa la polvere quanto più possibile
  • miscela 50/50 vinavil e acqua, stendere sul piano senza lesinare, deve esserci la possibilità di “spremere” la colla da sotto la carta una volta applicata
  • connesso al punto precedente, se il piano è un legno poroso o appena levigato e molto “asciutto”, occorrerà stendere una quantità maggiore di base
  • usare un pennello per verniciare la colla, se il fondo è poroso verniciare leggermente anche il retro del foglio di carta da applicare
  • posare il foglio nella posizione desiderata, e usare una specie di spatola morbida per stenderlo energicamente spremendo via i residui di colla sottostanti, ho usato con successo una “linguina” in gomma di quelle adatte a impastare le creme nelle ciotole e versarle nelle tortiere successivamente
  • dopo il passaggio precedente normalmente la colla in eccesso passa attraverso il foglio di carta fino a bagnare la superficie superiore, ma nel caso ripassare delicatamente col pennello e poca colla
  • decidere sin da subito il tipo di disposizione, in ogni caso è preferibile iniziare in un punto ed estendersi da quello, piuttosto che applicare i fogli in punti separati e proseguire irregolarmente; la disposizione a griglia è più semplice e efficiente, giacché richiede il minor numero possibile di fogli, ma quella casuale, con i fogli in obliquo e parzialmente sovrapposti, seppur richieda più fogli, risulta normalmente anche più gradevole
  • nel caso vadano ritagliate parti di foglio, il risultato è sia esteticamente sia tecnicamente più piacevole se vengono piuttosto strappati lungo i margini (le fibre di carta frastagliata si prestano meglio all’adesione)
  • sei margini di alcuni fogli tendono ad alzarsi, è preferibile intervenire subito prima dell’asciugatura, sollevandoli finché non si avverte un minimo di resistenza, e applicando sotto, sia su piano che retro foglio, un po’ di colla aggiuntiva col pennello, stendendo bene nuovamente con la spatola
  • attendere l’asciugatura completa (asciutezza e compattezza ben avvertibili al tocco) per i passaggi successivi di colla, che dovrebbero contenere una percentuale maggiore di vinilica rispetto al passaggio iniziale
  • [varie ed eventuali da aggiungere a proseguimento del progetto]

Titanium backup doesn’t restore on latest Android version

If you found the latest version of Titanium  Backup (now almost one year old with no recent updates…) cannot restore your apps data anymore on Android 10, this solution was found in the comments on the play store, by Stranger Stunts, published on 9/12/20.

Turn off “Verify apps over USB” in Developer Options, then turn off “Play protect” in the Play Store.

I didn’t test it properly but I remember last time I had such a problem I found a similar solution in the same fortuitous way, and it worked, but I didn’t have the idea to save it somewhere.

So I’m saving it on my blog for future reference.

Clone raspberry disk TO newer/larger disk/SD/SSD

I was switching from a 120GB SSD on my Raspberry Pi 4, to a 240GB one.

Found this and I cloned the command in the opening question:

sudo dd if=/dev/originaldisk of=/dev/destinationdisk bs=4096 conv=sync,noerror

where I used /dev/disk/by-id/... handles to make sure I was pointing to the correct SSD’s (otherwise,  had I swapped them, a huge mess would happen).

The resulting SSD was a perfect copy down to partition ID, so the cmdline.txt file under /boot/mounted from a FAT partition on the SD was starting the system off the new disk as if nothing happened.

I just tested it for the inverse situation.

On a Raspberry Pi 3, the running disk was a 240GB SSD, but it was pretty much wasted space since it was hosting a less than 4GB root partition, so I wanted to switch it to the 120GB SSD that I took out of the Raspi4.

I ran the above command, and I allowed myself the luxury to just Ctrl-C out of it after the first 10GB had been copied over, because actually just 4GB of the disk were being used.

Guess what, turned off the system, put the second SSD in place of the first, and the system booted perfectly.

So, how do you check the progress of a running dd command, you might ask?

Well, with the progress tool, naturally!

sudo apt install progress

first, and then, right after dd has started,

sudo progress -wm

This will clear the screen, and have the current status of the copy being shown and updated, while the copy is still running, so use of byobu (go search for that) is highly recommended.

The sudo is there because dd was started as root, so progress won’t be able to access its status unless ran with same privileges.

Disclaimer: using dd to clone a running disk might create inconsistencies where other running processes change the disk contents while the copy is running, and the resulting copy has part “old”, and part “new” content. Usually, this doesn’t matter, or might not happen at all if all the other processes access either tmpfs partitions or another disk, but in the end only you know what your system does, so thread with caution.

Get list of cases in a PHP switch statement

Like the title says, you have a PHP script where a (supposedly long) case switch statement is placed, and you want to programmatically get a list of all the strings for each case.

My use case is, I have a Telegram bot for my own private use, which does several actions, all different among themselves, when receiving user input from a specific account (mine).

The command strings are predetermined, so I have a -long- list of cases like so:

switch(strtolower($text)) {
    case "blah1":
        dosomething1();
        break;
    case "blah2":
        file_put_contents($somefile,2);
        break;
    case "blah3":
        echo file_get_contents($someurl);
        break;
    // [...]
    case "blah12":
        exec('php somescript.php > /tmp/somescript.log 2>&1 &');
        break;
}

I am adding new commands all the time, with the most different functions, and I might even forget some neat functions exist, so I wanted to implement a function where, in reply to a certain command, the bot lists all possible other commands (a --help function of sorts if you might).

They cannot be simply put inside an array, to be neatly listed at my pleasure, not with a useless excercise of my patience. Also, the listing functionality comes second, the first utility is semantical appropriatedness.

Let’s first say that there is no builtin function in PHP to get a list of cases in switch statement but you can still hack a function yourself.

The following solution is very ugly, but it will work on a simple code, and I would use this only if both of following conditions are verified:

  1. You are the only user of the script (my telegram bot takes into account commands only if they come from my account)
  2. the whole code in the script file basically revolves around the case switch and not much else

This scenario perfectly fits my case, so here’s what I did:

preg_match_all('/case \"([a-z0-9\s]+)\"\:/', file_get_contents(__FILE__), $matches);

You then can use:

foreach ($matches[1] as $casestring) {
    //...
}

or rather, as I actually did in the end, I simply returned:

$reply=implode("\n",$matches[1]);

7zip compression test of Raspberry backup image

I regularly backup the Raspbian system of my several Raspberry Pi’s, for reasons that anyone owning and using a Raspberry Pi knows.

With time you end up always wanting more, and I want to upload backups on the cloud for that additional layer of extra safety; cloud space, though, is either free and very limited, or quite costly to mantain, hence the smaller the files you upload, the more practical is sending them online.

With this purpose in mind, I wanted to try several compression options, using the same source file (a 3.7GB image file produced by my latest version of RaspiBackup -the “bleeding edge” which right now is in its own branch), but changing some parameters from the default “Ultra settings” (the one you can find in 7z manpage).

All tests were done on a non overclocked Raspberry Pi 4 with 4GB of RAM.

First test goes with the “ultra settings” comandline found in 7z manpage:

time 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on archive.7z source.img

7-Zip [32] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,32 bits,4 CPUs LE)

Scanning the drive:
1 file, 3981165056 bytes (3797 MiB)

Creating archive: archive.7z

Items to compress: 1


Files read from disk: 1
Archive size: 695921344 bytes (664 MiB)
Everything is Ok

real    50m33.638s
user    73m16.589s
sys     0m44.505s

Second test builds on this, and increases the dictionary size to 128MB (which is, alas, the maximum allowed for 32bit systems as per 7zip documentation, any value above this will throw an error on the raspberry):

time 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=128m -ms=on archive.7z source.img

7-Zip [32] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,32 bits,4 CPUs LE)

Scanning the drive:
1 file, 3981165056 bytes (3797 MiB)

Creating archive: archive.7z

Items to compress: 1


Files read from disk: 1
Archive size: 625572636 bytes (597 MiB)
Everything is Ok

real    59m54.703s
user    80m50.340s
sys     0m55.886s

Third test puts another variable in the equation, by adding the -mmc=10000 parameter, which tells the algorithm to cycle ten thousand times to find matches in the dictionary, hence increasing the possibility of a better compression, from the default number of cycles which should be in this case less than 100.

time 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=128m -mmc=10000 -ms=on archive.7z source.img

7-Zip [32] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,32 bits,4 CPUs LE)

Scanning the drive:
1 file, 3981165056 bytes (3797 MiB)

Creating archive: archive.7z

Items to compress: 1


Files read from disk: 1
Archive size: 625183257 bytes (597 MiB)
Everything is Ok

real    77m53.377s
user    99m48.431s
sys     0m39.215s

I then tried one last command line that I found on Stack Exchange network:

time 7z a -t7z -mx=9 -mfb=32 -ms -md=31 -myx=9 -mtm=- -mmt -mmtf -md=128m -mmf=bt3 -mpb=0 -mlc=0 archive.7z source.img

and I cannot find that answer anymore but it boasted the best compression rate ever (yeah, I imagine, everything was set to potential maximum). This commandline I had to tone down, because it implied increasing to the maximum possibile the dictionary size (which is 1536MB, but it’s not feasible on 32bit system which are limited to 128MB) and also the fast bytes to its maximum of 273.

I always got an error though:

ERROR: Can't allocate required memory!

even by gradually decreasing the -mfb (fast bytes) down to 32; even if I completely removed the fast bytes parameter. At this point I simply desisted.

So, onto the

Conclusions:

You should definitely pump up the dictionary size to its limit of 128MB, because it yields a discrete compression increase (down to 15.7% from 17.5%, so 10% smaller). According to this post the time increase must be measured as “user+sys”), so it’s 74 minutes of CPU time for first example, 81.75 minutes for the second, and 100.5 minutes for the third. The difference in CPU time between the first and second is still in the ballpark of 10%, so that additional time gets practically converted in better compression, I’ll take it.

Interestingly, increasing the matching cycles didn’t bring ANY increase in compression, at the expense of a whopping 25% increase in processing time (actually it did when I compared the exact file sizes, and it was negligible at just a few hundred kilobytes less).

Overall, this is is a great result, as the total free space in that image should be around 300MB, so the rest is all real data compression.