In need of a simple JS/CSS comment and white space stripper, I found not one useable tool. So, as usual, I wrote my own to strip and pack all CSS/JS into convenient archives. Not only does it reduce page load time and thus improve the user experience, it reduces traffic payload and the number of requests - a small step towards more sustainability for web pages.
If there are no file names given in -js or -css mode, stdin is used as input.
I use a make target in my projects to create minified and precompressed versions of the JS/CSS files:
SOURCEminify_v2.tgz v2, 2020-11-28
Corona lockdown.. finally some time to build a recipe database for my collection of vegan recipes with a query system similar to that I built 20 years ago for a friend's organic store in Marburg:
German only (for the moment :).
I needed a watchdog with variable timeouts during the lifecycle of the supervised process - longer timeouts during startup/initialisation, shorter during interactive operation. Since I could not find one, I wrote my own:
- no library dependencies (except libc)
- no config files, single binary
- ideal for embedded systems
- support for kernel watchdogs
- permission check via UID and program name
- millisecond precision
I find it so easy to use that I also run it on my web servers to monitor my daemons.
A process that wants to be monitored creates a file with unique filename (e.g. command name + pid) in /run/watchdog. The file contains the following three lines:
- command name is the name of the running process as in /proc/<PID>/command,
- pid is the PID of the process, and
- timeout is the timeout in milliseconds.
- the program name given in the file in /run/watchdog matches the name in /proc/<PID>/comm, and
- the EUID of the process (as in /proc/<PID>/status) is the same as the UID of the file in /run/watchdog
All watchdogs in /dev/watchdogX are pinged every WATCHDOGTIMEOUT ms and will receive the "Magic Close" upon exit of watchdogd.
Simply run 'watchdogd' at startup. If /var/run/watchdog does not exist, it will be created.
Send the process a SIGINT or SIGTERM to exit. These signals are caught, watchdogd writes the magic close byte to all system watchdogs and exits gracefully. Any files in /var/run/watchdog are kept in place, so after a restart of watchdogd it will resume operation immediately.
LOGGINGAll starts, shutdowns, process killings and errors are logged via syslog and stdout/stderr.
To use watchdogd in your program, simply include watchdogd.h and call watchdog_update() before any previous timeout runs out. To turn off the watchdog, call watchdog_disable():
Make sure that "myapp" is the EXACT command name of your application as it appears in /proc/<PID>/comm.
- /var/run should be tmpfs so you do not wear out your flash
- if you cache your pid make sure to reset it in the child process after fork()ing
If you should ever be in a situation where you have a piece of hardware on your bench without schematics, nobody to answer questions and you have to figure out where those pins are connected to.. gpiofinder to the rescue!
gpiofinder utilizes all GPIOs not already in use (e.g. because configured as dedicated periphery) and performs a binary search, so within log2(N) steps you should have your pin identified.
Why not as shell script? Embedded systems often have minimal shells with very limited features. Before building a full featured bash, hacking together a small C program seemed more feasable.
- Connect an oscilloscope or level meter to the GPO you are identifying
- Run gpiofinder with the maximum number of gpios as argument, e.g. 223 on the i.MX6
- Answer the questions with y/n:
$ ./gpiofinder 223 Initializing all GPOs to 0.. Is the level you are looking for currently low? (y/n) y Beginning search.. Enabling 0..111..did the level go up? (y/n) y Enabling 0..55..did the level go up? (y/n) y Enabling 0..27..did the level go up? (y/n) y Enabling 0..13..did the level go up? (y/n) n Enabling 14..27..did the level go up? (y/n) y Enabling 14..20..did the level go up? (y/n) y Enabling 14..17..did the level go up? (y/n) n Enabling 18..20..did the level go up? (y/n) y Enabling 18..19..did the level go up? (y/n) y Enabling 18..18..did the level go up? (y/n) n Enabling 19..19..did the level go up? (y/n) y GPIO=19
This script expects an Ubuntu version (YY.MM or name) as argument, pulls the files and creates a docker image. This comes in handy if your company's firewall policy forbids access to docker repositories or you want to build your own base images.
Make sure your version of debootstrap supports the Ubuntu versions you want to install.
SOURCEcreate_image.sh v1, 2019-11-12
For automated tests of user input, not connected input boards or buttons that are not there yet, I wrote this small tool to inject keypresses in the event system.
Will enter F1 a b c with a 200ms delay. For a list of all supported key names please look in the source, you can easily add new keys or other events.
A kernel with CONFIG_INPUT_UINPUT support.
To experiment with different PWM configurations to reduce display flickering I wrote this little tool. It reads and writes the IMX.6 registers and bypasses the Linux drivers.
Example: To set the PWM clock of PWM 1 to 15 kHz and the duty cycle to 50%, run
To read the registers of a PWM peripheral, run
A client wanted to build a push button board connected to a rpi to trigger scripts in order to automate scene recall, audio routing and quick switching of setups. This is accomplished by this small daemon that listens to GPI changes and runs scripts depending on the type of the event.
If you want to have to use a GPI, create one or more scripts in /var/lib/gpiod/scripts with the following name(s):
- <GPI>.sh for raising or falling edge (any change triggers the script)
- <GPI>_up.sh for raising edge
- <GPI>_down.sh for falling edge
As usual, the GPIOs have to be configured in the system in order to use them. You can do this yourself (by writing the necessery values to /sys/class/gpio/...) or use the scripts provided in the archive:
- edit gpiod.conf so the list of GPIs and GPOs reflect your hardware setup
- run create_gpios.sh and run_gpiod.sh at startup (in that order!)