diff --git a/README.md b/README.md
index ae0c9e9..4b895ad 100644
--- a/README.md
+++ b/README.md
@@ -235,76 +235,123 @@ start ipp-usb when needed.
sudo snap install docker
```
-#### Step-by-Step Guide
+#### **Running the `ipp-usb` Container with Persistent Storage**
-You can pull the `ipp-usb` Docker image from the GitHub Container Registry.
+To run the `ipp-usb` container while ensuring that its state persists across restarts, follow these steps.
-**From GitHub Container Registry**
-To pull the image from the GitHub Container Registry, run the following command:
+#### **1. Pull the `ipp-usb` Docker Image**
+The latest image is available on the GitHub Container Registry. Pull it using:
```sh
- sudo docker pull ghcr.io/openprinting/ipp-usb:latest
+sudo docker pull ghcr.io/openprinting/ipp-usb:latest
```
-To run the container after pulling the image, use:
+#### **2. Create Persistent Storage Volumes**
+To ensure that configuration settings and printer state persist across container restarts, create two Docker volumes:
+
```sh
- sudo docker run -d --network host \
- -v /dev/bus/usb:/dev/bus/usb:ro \
- --device-cgroup-rule='c 189:* rmw' \
- --name ipp-usb \
- ghcr.io/openprinting/ipp-usb:latest
-```
+sudo docker volume create ipp-usb-state
+sudo docker volume create ipp-usb-conf
+```
+
+These volumes store:
-- `--network host`: Uses the host network, ensuring IPP-over-USB and Avahi service discovery work correctly.
-- `-v /dev/bus/usb:/dev/bus/usb:ro`: Grants the container read-only access to USB devices.
-- `--device-cgroup-rule='c 189:* rmw'`: Grants the container permission to manage USB devices (189:* covers USB device nodes).
+- **`ipp-usb-state` (`/var/ipp-usb/`)**
+ - Device state files (`/var/ipp-usb/dev/`) – Ensures stable TCP port allocation and DNS-SD name resolution.
+ - Lock files (`/var/ipp-usb/lock/`) – Prevents multiple instances from running simultaneously.
+ - Log files (`/var/log/ipp-usb/`) – Can be optionally mounted if needed for debugging.
+
+- **`ipp-usb-conf` (`/etc/ipp-usb/`)**
+ - Configuration file (`/etc/ipp-usb/ipp-usb.conf`) – Stores user-defined settings.
+ - Quirks files (`/etc/ipp-usb/quirks/`) – Contains printer-specific workarounds.
+
+#### **3. Run the Container with Required Mounts**
+Start the container with appropriate options:
-To check the logs of `ipp-usb`, run:
```sh
- sudo docker logs -f ipp-usb
+sudo docker run -d --network host \
+ -v /dev/bus/usb:/dev/bus/usb:ro \
+ -v ipp-usb-state:/var/ipp-usb \
+ -v ipp-usb-conf:/etc/ipp-usb \
+ --device-cgroup-rule='c 189:* rmw' \
+ --name ipp-usb \
+ ghcr.io/openprinting/ipp-usb:latest
```
+- **`--network host`** → Uses the host’s network to enable proper IPP-over-USB and Avahi service discovery.
+- **`-v /dev/bus/usb:/dev/bus/usb:ro`** → Grants read-only access to USB devices for printer detection.
+- **`-v ipp-usb-state:/var/ipp-usb`** → Mounts the persistent storage volume for printer state, lock files, and logs.
+- **`-v ipp-usb-conf:/etc/ipp-usb`** → Ensures configuration and quirks files persist across reboots.
+- **`--device-cgroup-rule='c 189:* rmw'`** → Grants read, write, and management permissions for USB printers inside the container.
+
+
### Building and Running `ipp-usb` Locally
#### Prerequisites
-**Docker Installed**: Ensure Docker is installed on your system. You can download it from the [official Docker website](https://www.docker.com/get-started) or from the Snap Store:
+1. **Docker Installed**: Ensure Docker is installed on your system. You can download it from the [official Docker website](https://www.docker.com/get-started) or from the Snap Store:
```sh
sudo snap install docker
```
-**Rockcraft**: Rockcraft should be installed. You can install Rockcraft using the following command:
+2. **Rockcraft**: Rockcraft should be installed. You can install Rockcraft using the following command:
```sh
sudo snap install rockcraft --classic
```
-#### Step-by-Step Guide
-
-**Build the `ipp-usb` Rock Image**
+**To Build and Run the `ipp-usb` Rock Image Locally, follow these steps**
-The first step is to build the Rock from the `rockcraft.yaml`. This image will contain all the configurations and dependencies required to run `ipp-usb`.
+#### **1. Build the `ipp-usb` Rock Image**
+The first step is to build the Rock image from the `rockcraft.yaml` configuration file. This image will include all required dependencies and configurations for `ipp-usb`.
-Navigate to the directory containing `rockcraft.yaml`, then run:
+Navigate to the directory containing `rockcraft.yaml` and run:
```sh
rockcraft pack -v
-```
+```
-**Compile to Docker Image**
+#### **2. Convert the Rock Image to a Docker Image**
+Once the `.rock` file is built, convert it into a Docker image using:
+```sh
+sudo rockcraft.skopeo --insecure-policy copy oci-archive: docker-daemon:ipp-usb:latest
+```
+
+#### **3. Create Persistent Storage Volumes**
+To ensure that configuration settings and printer state persist across container restarts, create two Docker volumes:
-Once the `.rock` file is built, compile a Docker image from it using:
```sh
- sudo rockcraft.skopeo --insecure-policy copy oci-archive: docker-daemon:ipp-usb:latest
-```
+sudo docker volume create ipp-usb-state
+sudo docker volume create ipp-usb-conf
+```
-**Run the `ipp-usb` Docker Container**
+These volumes store:
+
+- **`ipp-usb-state` (`/var/ipp-usb/`)**
+ - Device state files (`/var/ipp-usb/dev/`) – Ensures stable TCP port allocation and DNS-SD name resolution.
+ - Lock files (`/var/ipp-usb/lock/`) – Prevents multiple instances from running simultaneously.
+ - Log files (`/var/log/ipp-usb/`) – Can be optionally mounted if needed for debugging.
+
+- **`ipp-usb-conf` (`/etc/ipp-usb/`)**
+ - Configuration file (`/etc/ipp-usb/ipp-usb.conf`) – Stores user-defined settings.
+ - Quirks files (`/etc/ipp-usb/quirks/`) – Contains printer-specific workarounds.
+
+#### **4. Run the Container with Required Mounts**
+Start the container with appropriate options:
```sh
- sudo docker run -d --network host \
- -v /dev/bus/usb:/dev/bus/usb:ro \
- --device-cgroup-rule='c 189:* rmw' \
- --name ipp-usb \
- ipp-usb:latest
+sudo docker run -d --network host \
+ -v /dev/bus/usb:/dev/bus/usb:ro \
+ -v ipp-usb-state:/var/ipp-usb \
+ -v ipp-usb-conf:/etc/ipp-usb \
+ --device-cgroup-rule='c 189:* rmw' \
+ --name ipp-usb \
+ ipp-usb:latest
```
+- **`--network host`** → Uses the host’s network to enable proper IPP-over-USB and Avahi service discovery.
+- **`-v /dev/bus/usb:/dev/bus/usb:ro`** → Grants read-only access to USB devices for printer detection.
+- **`-v ipp-usb-state:/var/ipp-usb`** → Mounts the persistent storage volume for printer state, lock files, and logs.
+- **`-v ipp-usb-conf:/etc/ipp-usb`** → Ensures configuration and quirks files persist across reboots.
+- **`--device-cgroup-rule='c 189:* rmw'`** → Grants read, write, and management permissions for USB printers inside the container.
+
### Accessing the Container Shell
To enter the running `ipp-usb` container and access a shell inside it, use:
@@ -313,22 +360,105 @@ To enter the running `ipp-usb` container and access a shell inside it, use:
```
This allows you to inspect logs, debug issues, or manually run commands inside the container.
-### Configuration
+### Configuration
-The `ipp-usb` container uses a configuration file located at:
+The `ipp-usb` container uses a configuration file located at:
+```sh
+/etc/ipp-usb/ipp-usb.conf
```
-/etc/ipp-usb.conf
+By default, the container uses the built-in configuration, which can be modified from inside the container.
+
+**Modifying the Configuration File Inside the Container**
+
+#### **1. Enter the Running Container**
+Use the following command to access the container’s shell:
+```sh
+sudo docker exec -it ipp-usb bash
```
-To customize the configuration, mount a modified config file:
+
+#### **2. Open the Configuration File in Nano**
+Once inside the container, open the configuration file using `nano`:
```sh
- sudo docker run -d --network host \
- -v /dev/bus/usb:/dev/bus/usb:ro \
- --device-cgroup-rule='c 189:* rmw' \
- -v /path/to/custom/ipp-usb.conf:/etc/ipp-usb.conf:ro \
- --name ipp-usb \
- ghcr.io/openprinting/ipp-usb:latest
+nano /etc/ipp-usb/ipp-usb.conf
```
+#### **3. Edit and Save the File**
+- Make the necessary changes to the file.
+- Press `CTRL + X`, then `Y`, and hit `Enter` to save the changes.
+
+#### **4. Restart the Container to Apply Changes**
+Exit the container and restart it to apply the updated configuration:
+```sh
+sudo docker restart ipp-usb
+```
+
+### **Viewing Logs in the `ipp-usb` Container**
+
+The `ipp-usb` container logs important events and errors to `/var/log/ipp-usb/`. Logs are categorized into:
+
+- **Main log file:** `/var/log/ipp-usb/main.log` → Captures overall service activity, including errors and general events.
+- **Per-device logs:** `/var/log/ipp-usb/.log` → Individual log files for each detected printer, helpful for troubleshooting device-specific issues.
+
+#### **1. Using Docker Logs**
+
+To view real-time logs from the running container, use:
+```sh
+sudo docker logs -f ipp-usb
+```
+- The `-f` flag follows the logs in real-time.
+- Replace `ipp-usb` with your actual container name if different.
+
+#### **2. Viewing Logs Inside the Container**
+
+If you need to inspect logs manually, first enter the container shell:
+```sh
+sudo docker exec -it ipp-usb bash
+```
+
+Once inside the container, you can use the following commands:
+
+#### **2.1 Monitor Logs in Real-Time**
+
+- **Main log file:**
+ ```sh
+ tail -f /var/log/ipp-usb/main.log
+ ```
+ This continuously displays new log entries for the entire service.
+
+- **Per-device log file (Replace `` with your printer's identifier):**
+ ```sh
+ tail -f /var/log/ipp-usb/.log
+ ```
+
+#### **2.2 Display Full Log Files**
+
+- **Show full contents of the main log file:**
+ ```sh
+ cat /var/log/ipp-usb/main.log
+ ```
+
+- **Show logs for a specific device:**
+ ```sh
+ cat /var/log/ipp-usb/.log
+ ```
+
+#### **2.3 List Available Device Logs**
+
+To see all available per-device log files, run:
+```sh
+ls /var/log/ipp-usb/
+```
+
+#### **3. Persisting Logs Across Container Restarts**
+
+If you want logs to persist across container restarts, you should mount the log directory using a Docker volume or a host directory.
+
+**Required Docker Flags for Log Persistence:**
+- `-v :/var/log/ipp-usb` → Mounts a Docker volume for log persistence.
+- **or**
+- `-v :/var/log/ipp-usb` → Mounts a host directory to retain logs outside the container.
+
+These options ensure that logs remain available even after the container stops or is recreated, allowing for easier troubleshooting and auditing.
## Installation from source
diff --git a/rock/rockcraft.yaml b/rock/rockcraft.yaml
index 5d918c2..5e3ccf3 100644
--- a/rock/rockcraft.yaml
+++ b/rock/rockcraft.yaml
@@ -9,6 +9,7 @@ description: |
license: Apache-2.0
adopt-info: ipp-usb
+run-user: _daemon_
platforms:
amd64:
@@ -16,8 +17,8 @@ platforms:
armhf:
services:
- dbus:
- command: /scripts/run-dbus.sh
+ avahi-daemon:
+ command: /scripts/run-avahi.sh
override: replace
on-failure: restart
startup: enabled
@@ -27,7 +28,7 @@ services:
startup: enabled
override: replace
on-failure: restart
- after: [dbus]
+ after: [avahi-daemon]
parts:
goipp:
@@ -114,35 +115,182 @@ parts:
make -j$CRAFT_PARALLEL_BUILD_COUNT
make install DESTDIR=$CRAFT_PART_INSTALL
- avahi-daemon:
- plugin: nil
- build-packages:
- - avahi-daemon
- overlay-packages:
+ avahi:
+ plugin: autotools
+ source: https://github.com/avahi/avahi.git
+ source-type: git
+ autotools-configure-parameters:
+ - --prefix=/usr
+ - --disable-qt3
+ - --disable-qt4
+ - --disable-qt5
+ - --disable-gtk
+ - --disable-gtk3
+ - --disable-gdbm
+ - --disable-python
+ - --disable-pygtk
+ - --disable-python-dbus
+ - --disable-mono
+ - --disable-monodoc
+ - --disable-manpages
+ - --disable-xmltoman
+ - --with-avahi-user=_daemon_
+ - --with-avahi-group=_daemon_
+ # - --with-avahi-priv-access-group=netdev
+ # - --with-distro=debian
+ - --disable-gobject
+ - --datadir=/usr/share
+ - --libdir=/usr/lib/${CRAFT_ARCH_TRIPLET_BUILD_FOR}
+ - --with-systemdsystemunitdir=/usr/lib/systemd/system
+ - --localstatedir=/var
+ - --sysconfdir=/etc
+ build-packages:
+ - g++
+ - gcc
+ - gettext
+ - intltool
+ - libdaemon-dev
+ - libdbus-1-dev
+ - libevent-dev
+ - libexpat1-dev
+ - libglib2.0-dev
+ - libsystemd-dev
+ - xmltoman
+ override-build: |
+ craftctl default
+ # for reference sort systemd service files
+ sed -i \
+ -e 's|\(.*\)avahi-daemon -s.*|\1avahi-daemon -s --no-drop-root|g' \
+ -e 's|\(.*\)avahi-daemon -r.*|\1avahi-daemon -r --no-drop-root|g' \
+ ${CRAFT_PART_INSTALL}/usr/lib/systemd/system/avahi-daemon.service
+ mkdir -p \
+ ${CRAFT_PART_INSTALL}/usr/lib/systemd/system/multi-user.target.wants
+ ln -sf \
+ ../avahi-daemon.service \
+ ${CRAFT_PART_INSTALL}/usr/lib/systemd/system/multi-user.target.wants/avahi-daemon.service
+ mkdir -p "${CRAFT_PART_INSTALL}/usr/share/dbus-1/"
+ cp -r /usr/share/dbus-1/* "${CRAFT_PART_INSTALL}/usr/share/dbus-1/"
+ build-environment:
+ - LD_LIBRARY_PATH: "${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$CRAFT_STAGE/usr/lib"
+ override-prime: |
+ set -eux
+ craftctl default
+ sed -i 's/use-ipv6=yes/use-ipv6=no/' ${CRAFT_PRIME}/etc/avahi/avahi-daemon.conf
+ sed -i 's|messagebus|_daemon_|; //,/<\/policy>/d' $CRAFT_PRIME/usr/share/dbus-1/system.conf
+ sed -i 's///g; s///g' $CRAFT_PRIME/usr/share/dbus-1/system.d/avahi-dbus.conf
+ stage-packages:
+ - libdaemon0
+ - libevent-2.1-7
- avahi-utils
- - libnss-mdns
- mdns-scan
+ # - libavahi-client3
+ # - libavahi-common3
+ stage:
+ - etc/avahi
+ - usr
+ - -usr/lib/**/libavahi-client.so*
+ - -usr/lib/**/libavahi-common.so*
+ - -usr/lib/**/*.acd
+ - -usr/lib/**/*.la
+ - -usr/lib/**/avahi
+ - -usr/lib/**/libavahi-glib*
+ - -usr/lib/**/libavahi-libevent*
+ - -usr/lib/**/libevent-*
+ # - -usr/lib/**/libnss_mdns*
+ - -usr/lib/**/pkgconfig
+ - -usr/include
+ - -usr/share/doc
+ - -usr/share/man
+ - -usr/share/locale
+ after: [ipp-usb]
+
+ utils:
+ plugin: nil
+ overlay-packages:
+ - python3
- dbus
- - libavahi-client3
- - libavahi-common3
- override-build: |
+ - libnss-mdns
+ - nano
+ override-prime: |
+ set -eux
craftctl default
- mkdir -p "${CRAFT_PART_INSTALL}/usr/share/dbus-1/"
- cp -r /usr/share/dbus-1/* "${CRAFT_PART_INSTALL}/usr/share/dbus-1/"
+
+ # Set up Avahi Daemon runtime directory
+ AVAHI_RUN_DIR="$CRAFT_PRIME/var/run/avahi-daemon"
+ mkdir -p "$AVAHI_RUN_DIR"
+ chown 584792:584792 "$AVAHI_RUN_DIR"
+ chmod 777 "$AVAHI_RUN_DIR"
+
+ # Set up D-Bus runtime directory
+ DBUS_RUN_DIR="$CRAFT_PRIME/var/run/dbus"
+ mkdir -p "$DBUS_RUN_DIR"
+ chown 584792:584792 "$DBUS_RUN_DIR"
+ chmod 777 "$DBUS_RUN_DIR"
+
+ # Set up IPP-USB runtime directories
+ IPP_USB_RUN_DIR="$CRAFT_PRIME/var/ipp-usb"
+ mkdir -p "$IPP_USB_RUN_DIR"
+ chown 584792:584792 "$IPP_USB_RUN_DIR"
+ chmod 770 "$IPP_USB_RUN_DIR"
+
+ # Set up lock directory for IPP-USB
+ LOCK_DIR="$IPP_USB_RUN_DIR/lock"
+ mkdir -p "$LOCK_DIR"
+ chown 584792:584792 "$LOCK_DIR"
+ chmod 770 "$LOCK_DIR"
+
+ # Set up dev directory for IPP-USB
+ DEV_DIR="$IPP_USB_RUN_DIR/dev"
+ mkdir -p "$DEV_DIR"
+ chown 584792:584792 "$DEV_DIR"
+ chmod 770 "$DEV_DIR"
+
+ # Set up log directory for IPP-USB
+ LOG_DIR="$CRAFT_PRIME/var/log/ipp-usb"
+ mkdir -p "$LOG_DIR"
+ chown 584792:584792 "$LOG_DIR"
+ chmod 770 "$LOG_DIR"
+
+ # Set up /etc/ipp-usb directory for configuration files
+ CONF_DIR="$CRAFT_PRIME/etc/ipp-usb"
+ mkdir -p "$CONF_DIR"
+ chown 584792:584792 "$CONF_DIR"
+ chmod 770 "$CONF_DIR"
+
+ # Create default ipp-usb.conf file if missing
+ CONF_FILE="$CONF_DIR/ipp-usb.conf"
+ touch "$CONF_FILE"
+ chown 584792:584792 "$CONF_FILE"
+ chmod 644 "$CONF_FILE"
+
+ # Set up quirks directory
+ QUIRKS_DIR="$CRAFT_PRIME/etc/ipp-usb/quirks"
+ mkdir -p "$QUIRKS_DIR"
+ chown 584792:584792 "$QUIRKS_DIR"
+ chmod 770 "$QUIRKS_DIR"
+
+ # Ensure ipp-usb binary is executable and owned by _daemon_
+ IPP_USB_BIN="$CRAFT_PRIME/usr/sbin/ipp-usb"
+ if [ -f "$IPP_USB_BIN" ]; then
+ chown root:584792 "$IPP_USB_BIN" # Owned by root, but executable by _daemon_
+ chmod 750 "$IPP_USB_BIN" # Only root and _daemon_ can execute
+ chmod u+s "$IPP_USB_BIN" # Set SUID so it runs as root when executed
+ fi
+ after: [ipp-usb, avahi]
scripts:
plugin: dump
source: scripts/
organize:
run-ipp-usb.sh: scripts/run-ipp-usb.sh
- run-dbus.sh: scripts/run-dbus.sh
+ run-avahi.sh: scripts/run-avahi.sh
override-prime: |
set -eux
craftctl default
if [ -f "$CRAFT_PRIME/scripts/run-ipp-usb.sh" ]; then
chmod +x "$CRAFT_PRIME/scripts/run-ipp-usb.sh"
fi
- if [ -f "$CRAFT_PRIME/scripts/run-dbus.sh" ]; then
- chmod +x "$CRAFT_PRIME/scripts/run-dbus.sh"
+ if [ -f "$CRAFT_PRIME/scripts/run-avahi.sh" ]; then
+ chmod +x "$CRAFT_PRIME/scripts/run-avahi.sh"
fi
- after: [ipp-usb, avahi-daemon]
+ after: [ipp-usb, avahi]
diff --git a/rock/scripts/run-avahi.sh b/rock/scripts/run-avahi.sh
new file mode 100644
index 0000000..2e539c1
--- /dev/null
+++ b/rock/scripts/run-avahi.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+set -eux
+
+# Start dbus-daemon in the background
+/usr/bin/dbus-daemon --system --nofork &
+
+# Wait for the D-Bus system bus to be ready
+while [ ! -e /var/run/dbus/system_bus_socket ]; do
+ echo "Waiting for dbus-daemon to initialize..."
+ sleep 1
+done
+
+# Start avahi-daemon after dbus-daemon is ready
+/usr/sbin/avahi-daemon -f /etc/avahi/avahi-daemon.conf --no-drop-root --debug
+
+# Keep the container running
+exec tail -f /dev/null
\ No newline at end of file
diff --git a/rock/scripts/run-dbus.sh b/rock/scripts/run-dbus.sh
deleted file mode 100644
index 11b902c..0000000
--- a/rock/scripts/run-dbus.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-set -eux
-
-echo "Creating system users..."
-
-# Check if users exist before attempting to create them
-if ! id -u systemd-resolve >/dev/null 2>&1; then
- useradd --system --no-create-home --shell /usr/sbin/nologin systemd-resolve
-fi
-
-if ! id -u systemd-network >/dev/null 2>&1; then
- useradd --system --no-create-home --shell /usr/sbin/nologin systemd-network
-fi
-
-echo "Ensuring necessary directories exist..."
-
-# Ensure /run/dbus exists with correct permissions
-if [ ! -d /run/dbus ]; then
- mkdir -p /run/dbus
- chmod 755 /run/dbus
- chown root:root /run/dbus
-fi
-
-echo "Starting dbus service..."
-
-# Start dbus and verify it's running
-service dbus start
-if ! pgrep -x "dbus-daemon" >/dev/null; then
- echo "Failed to start dbus-daemon!" >&2
- exit 1
-fi
-
-echo "Starting avahi-daemon..."
-
-# Start avahi-daemon and ensure it's running
-avahi-daemon --daemonize --no-drop-root
-if ! pgrep -x "avahi-daemon" >/dev/null; then
- echo "Failed to start avahi-daemon!" >&2
- exit 1
-fi
-
-echo "Services started successfully."
-
-# Keep the container alive using a foreground process
-exec sleep infinity
diff --git a/rock/scripts/run-ipp-usb.sh b/rock/scripts/run-ipp-usb.sh
index 77cb8d1..074fba7 100644
--- a/rock/scripts/run-ipp-usb.sh
+++ b/rock/scripts/run-ipp-usb.sh
@@ -1,19 +1,32 @@
#!/bin/sh
+set -eux
-#set -e -x
-
-# Create needed directories (ignore errors)
+# Create necessary directories
mkdir -p /etc/ipp-usb || :
+mkdir -p /etc/ipp-usb/quirks || :
+mkdir -p /var/ipp-usb/lock || :
+mkdir -p /var/ipp-usb/dev || :
mkdir -p /var/log/ipp-usb || :
-mkdir -p /var/lock || :
-mkdir -p /var/dev || :
-mkdir -p /usr/share/ipp-usb/quirks || :
+# Copy quirks files if not present
+cp -rn /usr/share/ipp-usb/quirks/* /etc/ipp-usb/quirks/ >/dev/null 2>&1 || :
# Put config files in place (do not overwrite existing user config)
-yes no | cp -i /usr/share/ipp-usb/quirks/* /etc/ipp-usb/quirks >/dev/null 2>&1 || :
if [ ! -f /etc/ipp-usb/ipp-usb.conf ]; then
- cp /usr/share/ipp-usb/ipp-usb.conf /etc/ipp-usb/ >/dev/null 2>&1 || :
+ cp /etc/ipp-usb.conf /etc/ipp-usb/ >/dev/null 2>&1
fi
+# Wait for avahi-daemon
+while true; do
+ if [ -f "/var/run/avahi-daemon/pid" ] || [ -f "/run/avahi-daemon/pid" ]; then
+ echo "[$(date)] avahi-daemon is active. Starting ipp-usb..."
+ break
+ fi
+ echo "[$(date)] Waiting for avahi-daemon to initialize..."
+ sleep 1
+done
+
+# Run ipp-usb with logging
+echo "[$(date)] Running ipp-usb..."
+
# Run ipp-usb with the provided command-line arguments
exec /usr/sbin/ipp-usb "$@"