To change the group and owner recursively, run the following command:
sudo chown -R <owner>:<group> . (don't forget the '.'!)
To see the output log of services et al, one can use the well-known tail command.
However, there's a much more convenient tool I've recently discovered: journalctl
journalctl has many, many features of which I find the following very interesting:
journalctl -b: same as dmesg
journalctl -u: shows the logs for a given service
journalctl -b can be used "as is":
pi@homerepli:~ $ journalctl -b
-- Logs begin at Fri 2021-10-22 16:42:35 CEST, end at Sun 2021-10-24 11:10:23 CEST. --
Oct 22 16:42:35 homerepli kernel: Booting Linux on physical CPU 0xf00
Oct 22 16:42:35 homerepli kernel: Linux version 5.10.63-v7+ (dom@buildbot) (arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-3ubuntu1) 8.4.0, GNU
d (GNU Binutils for Ubuntu) 2.34) #1459 SMP Wed Oct 6
Oct 22 16:42:35 homerepli kernel: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c5387d
Oct 22 16:42:35 homerepli kernel: CPU: div instructions available: patching division code
Oct 22 16:42:35 homerepli kernel: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Oct 22 16:42:35 homerepli kernel: OF: fdt: Machine model: Raspberry Pi 2 Model B Rev 1.1
Oct 22 16:42:35 homerepli kernel: random: fast init done
Oct 22 16:42:35 homerepli kernel: Memory policy: Data cache writealloc
Oct 22 16:42:35 homerepli kernel: Reserved memory: created CMA memory pool at 0x3a400000, size 64 MiB
Oct 22 16:42:35 homerepli kernel: OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
Oct 22 16:42:35 homerepli kernel: Zone ranges:
journalctl -u is interesting:
journalctl -u homecontrol.service
Shows the logs for a given service (here: homecontrol.service)
journalctl -f -u homecontrol.service
Shows the last (by default:10) lines of the given service and will continue to add the newest output to the end of the current output
journalctl -f --no-tail -u homecontrol.service
Same as above, but now also from the very beginning of the file. That also means that you will see outputs of previously started services. It's really the complete content of the service log file.
journalctl -f --no-tail -u homecontrol.service -o cat
Same as above, but with a less extended output: the extra info normally added by journalctl is now removed.
Example without -o cat:
Oct 24 11:14:23 homerepli homecontrol.sh[1263]: 24-10-2021 11:14:23 INFO HomeControl - Waiting for another 60 seconds...
Oct 24 11:15:23 homerepli homecontrol.sh[1263]: 24-10-2021 11:15:23 INFO HomeControl - Waiting for another 60 seconds...
Example with -o cat:
24-10-2021 11:14:23 INFO HomeControl - Waiting for another 60 seconds...
24-10-2021 11:15:23 INFO HomeControl - Waiting for another 60 seconds...
As one can see, the typical journalctl "prefix" is removed when using the -o cat option.
To see the content of journalctl from a certain date onwards, the following command can be used:
journalctl -f --no-tail -u homecontrol.service --since 2021-10-19 -o cat
If you started a service with the argument --user (see systemd for services, run as user below) then you also have to add the --user to the journalctl command like so:
journalctl --user -u symlink_wayland.service
There are many more features, but the above are the most interesting ones for me...
systemd is used to create and maintain services and they are run as root.
That means, you can't run something where a regular user id is used.
Once a service is created, the most important systemd commands are:
systemctl enable <service>
This command must be run as sudo and will enable the service. It will also create a symbolic link from /etc/systemd/system/default.target.wants/homecontrol.service to /lib/systemd/system/homecontrol.service
/lib/systemd/system is the directory where I made the homecontrol.service
/etc/systemd/system/default.target.wants is the directory chosen by the Linux system because in my service script there's a WantedBy=default.target install instruction
Enabling the service does not mean the service will be started implicitly! Therefore, you must run the command systemctl start <service> (as sudo).
systemctl disable <service>
This command will disable the service given. This means that with the next reboot, the service will not be started anymore.
That does not mean the running service will be stopped! Therefore, you must run the command systemctl stop <service> (as sudo) explicitly.
systemctl start <service>
This command will start the service and must be run as sudo.
Note: if you didn't enable the service, the service won't be restarted at the next reboot!
systemctl stop <service>
This command will stop the service and must be run as sudo.
If the service was enabled, the service will restart at the next reboot.
systemd status <service>
This will show the status of the service given (running, inactive, dead,...). You don't have to be sudo to run this command.
There are more options available for the systemctl command, but that'll do for now (and for me...).
Next to the root services, which all run in /lib/systemd/system or /usr/lib/systemd/system we also have services that can be run as the current user.
However, the location of those services and how to start them is slightly different compared to the "regular" services.
First off, the user services are located in a directory called ~/.config/systemd/user (create those directories if they don't exist yet).
In that user directory you can then have your user services. They will run with the user id of the user instead of the user id of the root like it is the case for the system services.
Example service:
A service that calls a bash script way.sh at start up. The bash script way.sh creates a link to the Wayland environment if it doesn't exist yet. Else, it first removes the link and then recreate it.
This trick was needed to have GUI applications (meld, gedit,...) work properly on Ubuntu 24.04 in wsl since there were issues with it (very slow start up, not full screen, no mouse reaction when clicking on menu bar items,...)
Script name:
way.sh
Script location:
/home/geertvc/mystuff/bashfiles
Script content:
#!/bin/bash
if [ -L /run/user/$(id -u)/wayland-0 ]
then
echo "Link found, remove it first"
rm /run/user/$(id -u)/wayland-0*
else
echo "Link not found, creating it"
fi
ln -s /mnt/wslg/runtime-dir/wayland-0* /run/user/$(id -u)/
Service name:
symlink_wayland.service
Service location:
/home/geertvc/.config/systemd/user
Service content:
[Unit]
Description=Symlink Wayland socket
[Service]
Type=oneshot
ExecStart=/home/geertvc/mystuff/bashfiles/way.sh
[Install]
WantedBy=default.target
Different ways to handle the service:
To start the service run the command systemctl --user start symlink_wayland.service
Then check the status of the service using the command systemctl --user status symlink_wayland.service
This is the output of that command:
geertvc@Win10:~$ systemctl --user status symlink_wayland.service
○ symlink_wayland.service - Symlink Wayland socket
Loaded: loaded (/home/geertvc/.config/systemd/user/symlink_wayland.service; disabled; preset: enabled)
Active: inactive (dead)
Apr 13 13:37:13 Win10 systemd[329]: Starting symlink_wayland.service - Symlink Wayland socket...
Apr 13 13:37:13 Win10 way.sh[381]: Link not found, creating it
Apr 13 13:37:13 Win10 systemd[329]: Finished symlink_wayland.service - Symlink Wayland socket.
It shows inactive (dead) since we didn't enable the service yet, we only started it.
To start the service automatically you just follow the regular service start procedure, except you add the parameter --user to it and you don't have to be sudo since you manage the service not as root but as a regular user (you yourself):
systemctl --user enable symlink_wayland.service
From here onwards, each time you log in into the system this script will run and the link will be (re)created.
Depending on the location you put your service, it has a different priority. This is the priority list:
/etc/systemd/system/ - Prio 1
/run/systemd/system/ - Prio 2
/lib/systemd/system/ - Prio 3
/usr/lib/systemd/system/ - Prio 3
Found here.
systemctl is the new mechanism in Linux to create services.
An interesting web site about systemctl can be found here. An interesting link about the general systemd mechanism can be found here.
systemctl can be used in combination with journalctl in that you can request journalctl to only show the content of the last time a service has been started up.
Each time a service is started, a unique UUID is created for that specific session. The trick is now to find that UUID and combine it with journalctl to show only the information of the last time the service has started.
How can this be accomplished?
Get the UUID.
Therefore, we can use the systemctl command like so:
systemctl show -p InvocationID --value homecontrol.service
Here, the -p parameter asks to the show parameter to give back the value (--value) of the invocation id (that is, the UUID) of the service. The invocation ID is requested by the show option InvocationID.
There are many more options for the show command. If you want to see them all, run the command systemctl show -p and then press twice the tab key. You will be asked if you want to see all of the 400+ options. If you're curious, press y...
Example:
pi@homerepli:~ $ systemctl show -p InvocationID --value homecontrol.service
07af3cb9cf1e495db83db8674ca3892b
Pass the UUID to the journalctl command.
Here we have two options:
Paste the UUID just found in the journalctl command like so:
journalctl -f --no-tail -u homecontrol.service -o cat \ _SYSTEMD_INVOCATION_ID="07af3cb9cf1e495db83db8674ca3892b"
A more "professional" way of working is to request the UUID on the fly. Therefore, one has to execute the command in between the two "" signs of the above command like so:
journalctl -f --no-tail -u homecontrol.service -o cat \
_SYSTEMD_INVOCATION_ID="$(systemctl show -p InvocationID --value homecontrol.service)"
The result of the command systemctl show -p InvocationID --value homecontrol.service is passed as a parameter to the _SYSTEMD_INVOCATION_ID (internal) variable.
There are many more internal variables available. Again, start typing the _SYSTEMD text and press the tab key twice. You will see all the possible _SYSTEMD candidates.
Next to _SYSTEMD, there are more variables available. Experiment with it if you're interested in knowing more about the systemd or journalctl command, but for now (and for me) that's sufficient!
There's unfortunately few documentation available for the possible systemd variables (at least, that's my impression...).
Systemd command Sysvinit command
systemctl start service_name service service_name start
systemctl stop service_name service service_name stop
systemctl restart service_name service service_name restart
systemctl status service_name service service_name status
systemctl enable service_name chkconfig service_name on
systemctl disable service_name chkconfig service_name off
When you install vim on the Raspberry Pi and then open a file using an existing Putty session and try to use the numerical keypad, you wil see that the cursor executes a movement instead of typing the numbers.
To overcome this, the following settings in Putty have to be changed for the session:
Open the Putty configuration and select Terminal -> Features. Then, check the item Disable application keypad mode.
Select Terminal -> Keyboard and select Linux in the section The Function keys and keypad
Save the changes for the current session.
Obviously, it's better to do those things immediately when creating a new session.
In some occasions you want to wait until another service is launched, before the next service should be launched. It is possible to accomplish this in the service itself. Below is an example:
First service
[Unit]
Description=First of two services
[Service]
ExecStart=/home/steve/play/systemd/oneAfterTheOther/first.sh
Type=oneshot
[Install]
WantedBy=multi-user.target
Second service
[Unit]
Description=Second of two services
After=first.service
[Service]
ExecStart=/home/steve/play/systemd/oneAfterTheOther/second.sh
Type=oneshot
[Install]
WantedBy=multi-user.target
The important statement is in the second service: "After". This will wait until the first service has finished, before it's launched.
Also important is to mention that the type of the two services should be "oneshot".
To check the correctness of the flow, you can run journalctl like so:
$ journalctl -u first -u second
-- Logs begin at Wed 2018-09-05 11:46:04 CDT, end at Wed 2018-09-05 11:51:54 CDT
Sep 05 11:46:21 sk-xenial-vm systemd[1]: Starting First of two services...
Sep 05 11:46:22 sk-xenial-vm first.sh[868]: sleep for 10 seconds
Sep 05 11:46:32 sk-xenial-vm first.sh[868]: ...and we're out
Sep 05 11:46:32 sk-xenial-vm systemd[1]: Started First of two services.
Sep 05 11:46:32 sk-xenial-vm systemd[1]: Starting Second of two services...
Sep 05 11:46:32 sk-xenial-vm second.sh[1104]: sleep for 2 seconds
Sep 05 11:46:34 sk-xenial-vm second.sh[1104]: ...and we're out
Sep 05 11:46:34 sk-xenial-vm systemd[1]: Started Second of two services.
The first shell script has a sleep built in, simulating a long task. As you can see, the second service is only started when the first one is finished.
If you want to search a text in a bunch of files, use the following command: grep -rwn <path> -e '<text>'
Example: grep -rwn . -e 'Can' will search for the text "Can" in all files in the current and subfolders.
Options:
-r: recursive
-w: search whole word
-n: show line numbers
If the word you're searching for contains the character ' then use double quotes "" to search for the text.
Example: grep -rwn . -e "Can't"
Example result:
pi@librecomputer:~/mystuff/git_repos/pigpio $ grep -rnw . -e "Can't"
grep: ./pigpio/DOC/dbase/pigpio.sqlite: binary file matches
./pigpio/DOC/src/defs/pigs.def:1778:Can't resolve tag 99
./pigpio/DOC/src/html/faq.html:251: printf("Can't connect to pigpio daemon\n");
./pigpio/EXAMPLES/CPP/IR_RECEIVER/test_ir_hasher.cpp:32: /* Can't instantiate a Hasher before pigpio is initialised. */
./pigpio/command.c:1414: fprintf(stderr, "Can't resolve tag %"PRIdPTR"\n", instr.p[1]);
./pigpio/pigpio.c:1721: DBG(DBG_ALWAYS, "Can't set permissions (%d) for %s, %m", perm, name);
./pigpio/pigpio.c:8272: SOFT_ERROR(PI_INIT_FAILED, "Can't lock %s", PI_LOCKFILE);
./pigpio/pigpio.py:895:Can't create callback thread.
./pigpio/pigpio.py:5254: s = "Can't connect to pigpio at {}({})".format(host, str(port))
./pigpio/pigpiod.c:371: if (gpioInitialise()< 0) fatal("Can't initialise pigpio library");
./pigpio/pigs.1:3261:Can't resolve tag 99
The search text can also contain more than one word.
Example: grep -rwn . -e "Can't connect"
Example result:
pi@librecomputer:~/mystuff/git_repos/pigpio $ grep -rnw . -e "Can't connect"
grep: ./pigpio/DOC/dbase/pigpio.sqlite: binary file matches
./pigpio/DOC/src/html/faq.html:251: printf("Can't connect to pigpio daemon\n");
./pigpio/pigpio.py:5254: s = "Can't connect to pigpio at {}({})".format(host, str(port))
Detailed information: see this page.
Extra: search case insensitive: grep -i <search_item>. Default, grep searches case sensitive.
To mount an SD card on Linux you have two options:
The SD card is put into a USB card reader
The SD card is put into an SD card adapter
In case the SD card is put into a USB card reader the SD card will be visible as a /dev/sdx device, where x is the letter [a-z] given by the Linux OS.
To find the device, run the command sudo fdisk -l. This will show you an overview of all the file disks on your Linux OS. Somewhere in that output you should see the SD card represented by a /dev/sdx.
If the SD card has different partitions, then you will also see the details like /dev/sdx1, /dev/sdx2 and so on (depending on the amount of partitions on the SD card).
Example:
.
.
.
Disk /dev/loop28: 7,26 MiB, 7614464 bytes, 14872 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdb: 59,48 GiB, 63864569856 bytes, 124735488 sectors
Disk model: Mass-Storage
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x4c4e106f
Device Boot Start End Sectors Size Id Type
/dev/sdb1 8192 532479 524288 256M c W95 FAT32 (LBA
/dev/sdb2 532480 3842047 3309568 1,6G 83 Linux
As you can see, in this example the SD card is found as being /dev/sdb and has two partitions: /dev/sdb1 and /dev/sdb2.
So far, you cannot use the SD card yet: it has to be mounted first.
To do this, you have again two options:
Make use of the standard /mnt directory that is part of the Ubuntu RFS.
sudo mount /dev/sdb1 /mnt
This will mount /dev/sdb1 to the /mnt mount point.
If you want to mount the second partition, replace the '1' with '2' in the above mentioned command.
Create mounting points yourself.
There's also a /media directory present as standard directory on the Ubuntu RFS. You can directly mount an SD card partition on the /media mounting point or you can create two subdirectories first to mount the two SD card partitions individually (you can do the same for the /mnt mounting point explained above of course).
sudo mkdir /media/sdb1
sudo mkdir /media/sdb2
Then you can mount the individual partitions on those mounting points respectively:
sudo mount /dev/sdb1 /media/sdb1
sudo mount /dev/sdb2 /media/sdb2
From here onwards you can now access the content of the partition(s) of the SD card.
To unmount the SD card you should run the command sudo umount /dev/sdb1 or sudo umount /dev/sdb2. Now you can remove the SD card from the PC.
_______________________________________________________________________________________________________________________________
In case you put your SD card in an SD card adapter then your SD card will be mounted as /dev/mmcblk0px as can be seen below after running the command sudo fdisk -l again:
Disk /dev/mmcblk0: 59,48 GiB, 63864569856 bytes, 124735488 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x4c4e106f
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 8192 532479 524288 256M c W95 FAT32
/dev/mmcblk0p2 532480 3842047 3309568 1,6G 83 Linux
However, the idea behind the mounting strategy is exactly the same as the one described above. Just replace sdbx with mmcblk0px instead in all the commands given.