You are not logged in.
I'm building a bash script application called "charge-notifier", designed to notify the device's battery status (if it's fully charged, going low, or so low it will go to sleep/hibernation by itself).
However, I have a few questions before I can turn it into a Linux package, in regards to where each file goes:
the SystemD.service — that goes to /usr/lib/systemd/system, then symlinks to /etc/systemd/system/*
The main bash script — any appropriate location for it?
A variable that determines to play notification or not — do I make that inside /etc/environment during install? Or within the script itself?
Folder for install/remove scripts (or entire folder of the app) — what location to place it besides /opt/ ?
I'd like to let you know that this will be my very first attempt at building a Linux package, and I have no prior experience in creating any application for Linux. (There are good responses on building bash script apps from the Ubuntu forums, but I'm not using that distro.)
Any help is appreciated. Thanks!
Link to the project:
https://github.com/ryanbarillos/charge-notifier
Last edited by ryanbarillos (2024-02-26 21:55:37)
Offline
You don't -- and it will horribly break -- want to make that a system wide system service , but an user one, logical difference for packaging it goes into /usr/lib/systemd/user and has some stipulations on the unit file: https://wiki.archlinux.org/title/Systemd/User and more specifically https://wiki.archlinux.org/title/System … user_units
As for the bash script -- assuming you're packaging it properly, see below --, the same spot all binaries go -- /usr/bin.
For something that's intended to run as a systemd service, you can embed variables directly as part of the service either inline with Environment=NAME=VALUE or in a file you can pick up with EnvironmentFile=, if it's just one variable I'd add it as part of the service and tell users to make use of systemd unit overrides if they want to change the default: https://wiki.archlinux.org/title/System … ided_units
Depends, assuming you want to package it for Arch you need neither of these if you're doing a proper PKGBUILD: https://wiki.archlinux.org/title/Creating_packages -- because pacman will handle that.
If you do want something generic, then I'd say yes, you place everything in /opt and tell the service to start the script from there.
Last edited by V1del (2024-02-26 11:24:27)
Offline
You don't -- and it will horribly break -- want to make that a system wide system service , but an user one, logical difference for packaging it goes into /usr/lib/systemd/user and has some stipulations on the unit file: https://wiki.archlinux.org/title/Systemd/User and more specifically https://wiki.archlinux.org/title/System … user_units
Well, I do intend it to be made a system-wide service for all user accounts, because this is a system feature found on Windows, and I want to implement the same on wherever the program will be installed on.
As a side note, on Android it won't make if this service were implemented of that same idea (not making it a system service) . It will be convoluted for the majority of phone users if each user profile on Android (at least on AOSP ROM's and modified Samsung OS's) were to have individual settings on when to alert low battery status, or how Charging Control / Battery Charge Limit works --- it will be a nightmare that will be demanded to be simplified from the top!
Given this, I don't see a good reason not to have this package reside only in the user space, when other systems have this embedded deep within their systems for any user of the host to access.
So, would there be places inside the system to appropriately place these files (i.e., for Arch Linux)?
---
(Don't worry about the idea of a generic package for Debian & Red Hat/Fedora distros and their derivatives at this point in time; I'm not ready for that yet.)
Last edited by ryanbarillos (2024-02-26 12:34:40)
Offline
We're not on Android nor on Windows, not sure what their relevance is here.
An user service is from the perspective of an user still "systemwide" if you place the file at that location I mentioned. Just that it has to be enabled per user -- you could enable the resulting user service globally so that it's valid and started for all users, though that can sometimes cause trouble for some system users as it might get started for those too, e.g. display managers or so.
But I know you've never ran your script with your service file, because the vast majority of the things you're doing are going to break in a system service context, all of which will be appropriately populated by the user service and your script does nothing that would need that level of system access.
As such, the places where you'd put the files would still be where I mentioned.
What's your end goal here? Is this for personal curiosity or are you actually thinking of distributing this to a wider audience?
Offline
FWIW that script is very inefficient. You have a continuous loop that checks the battery value many times each time through the loop. You should check *once* each time through the loop, then just use that value to determine what to do (perhaps with a `case` statement). The individual checks also spawn needless subshells. You don't need a subshell to read a value into a variable then test the variable (e.g., for "Charging"): just use `grep -q Charging /path/to/file` in the first place.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
if each user profile on Android (at least on AOSP ROM's and modified Samsung OS's)
…
Android is a single user system for very specific purposes.
designed to notify the device's battery status (if it's fully charged, going low, or so low it will go to sleep/hibernation by itself).
https://wiki.archlinux.org/title/Laptop … tery_level
As for pestering informing the users, it would be good practice to allow user control.
1. Skip the dialog.
Unprompted dialogs popping up into the users face is the worstmosthorrible UX sin you can commit.
They steal the focus and the user might accidentally click/enter them away and then be left with the worry what they just did.
Otoh notifications are defined and designed to be unprompted and typically allow control to ignore undesired ones.
2. As V1del pointed out: your script will not work (in most cases)
You'll have to obtain the list of (active) sessions, su into the relevant user, import the $DBUS_SESSION_BUS_ADDRESS and then send a notification.
However, making this a user service/daemon will not only spare you all of that but also make it opt-in.
Offline
We're not on Android nor on Windows, not sure what their relevance is here.
--{ Not to ignore the good insights you've shared, but I'd like to address this a little bit }--
What's your end goal here? Is this for personal curiosity or are you actually thinking of distributing this to a wider audience?
The latter a little bit, but primarily to emulate this system feature from our other OS's on Linux.
FWIW that script is very inefficient. You have a continuous loop that checks the battery value many times each time through the loop. You should check *once* each time through the loop
I'd like to learn of an efficient way for this loop to work (or perhaps discard the loop altogether, when possible). But based on what I'm getting from your recommendation, the loop is best run as such:
https://imgur.com/a/kMz2ijl
it would be good practice to allow user control.
1. Skip the dialog.
Unprompted dialogs popping up into the users face is the worstmosthorrible UX sin you can commit.
They steal the focus and the user might accidentally click/enter them away and then be left with the worry what they just did.
In terms of showing unprompted dialogs, it won't baffle me when Windows does it even on Windows 7 Windows 11, iOS, and Android over the years ( 1, 2 )
However, if you mean the constant pop-ups showing unprompted as the loop runs, I'll agree that that should show only once. However, with my current config of using the loop every few seconds, IDK how to stop that without ditching it altogether (if a method even exists, that's what I don't know
2. As V1del pointed out: your script will not work (in most cases)
You'll have to obtain the list of (active) sessions, su into the relevant user, import the $DBUS_SESSION_BUS_ADDRESS and then send a notification.However, making this a user service/daemon will not only spare you all of that but also make it opt-in.
I'll take the example of auto-cpufreq:
1. This script (now a GUI app) runs a system-wide service
2. The changes it makes on CPU governor based on when battery is charged/discharged is persistent across all local users
3. Every local user of the host doesn't have to enable this service individually to get the effects of the software (and save some battery)
----- Just enable it once with sudo systemctl enable --now auto-cpufreq, any user, and it's fully enforced across all users in that single host.
Pardon me if I seem to be stubborn from your perspective (I'm not, I'm trying to understand your point here), but I don't see the requirement of making this script very complicated for such a ubiquitous service to run. none of this $DBUS shenanigens should be necessary---that's asking for more trouble, and more load on someone inexperienced like me. I'll be glad to reconsider if such a case similar to what I'm about to results in a broken system in the past and can be cited here.
However, based on how other OS's have implemented this service (Windows, iOS & Android), and how auto-cpufreq is able to enforce governor changes to all users (not needing each local user in host to specify what CPU governor to use when charging/discharging), I find no necessity on making this project bigger than it should be, besides code optimizations.
I hope what I've replied makes sense, and so is my thought process going into this small project.
Offline
In terms of showing unprompted dialogs, it won't baffle me when Windows does it even on Windows 7 Windows 11, iOS, and Android over the years ( 1, 2 )
By that logic, we should be eating shit - like the vast majority of living individuals on the planet.
I don't see the requirement of making this script very complicated for such a ubiquitous service to run
Me neither, run it as a user service.
auto-cpufreq, like the udev hibernation trigger I linked you, doesn't try to talk to the user.
If you want to invade the GUI session of a user, you WILL have to engage in "this $DBUS shenanigens" - otherwise the system doesn't know you you want to talk to.
Try
sudo notify-send foo
Plain X11 will fall apart if XAUTHORITY isn't in the default spot (some DMs randomize the location), leaving aside that running GUI code as UID0 is a security nightmare tbw.
Offline
I'd like to learn of an efficient way for this loop to work (or perhaps discard the loop altogether, when possible). But based on what I'm getting from your recommendation, the loop is best run as such:
https://imgur.com/a/kMz2ijl
Yes. That's precisely what I was thinking written out in pseudo-code.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Try
sudo notify-send foo
Plain X11 will fall apart if XAUTHORITY isn't in the default spot (some DMs randomize the location), leaving aside that running GUI code as UID0 is a security nightmare btw.
I agree that notify-send won't work as root (or even su). If $DBUS is the only to get to the intended purpose, I'll implement it.
You'll have to obtain the list of (active) sessions, su into the relevant user, import the $DBUS_SESSION_BUS_ADDRESS and then send a notification.
Is is the only way? Or there may be an alternative that achieves sending notifications to the logged-in user?
From what I can find on D-Bus on Arch Wiki, it's very brief and lacks any meaningful explanation on the bus address (how to interpret it as the logged user)
Offline
From what I can find on D-Bus on Arch Wiki, it's very brief and lacks any meaningful explanation on the bus address (how to interpret it as the logged user)
Because that problem is entirely not part of dbus.
You'd use eg. w, loginctl or seatd for a list of sessions and then will have to import the environment from one of their reelvant processes.
See eg. https://gist.github.com/AladW/de1c5676d93d05a5a0e1
Offline