···11+# gentle.sh
22+33+Run commands with limited system resources to prevent builds from hammering system responsiveness.
44+55+## Table of Contents
66+77+- [Background](#background)
88+- [Install](#install)
99+- [Usage](#usage)
1010+- [Resource Limits](#resource-limits)
1111+- [Examples](#examples)
1212+1313+## Background
1414+1515+When running large builds or heavy computational workloads, system responsiveness can suffer. `gentle.sh` wraps any command in a systemd-run scope with aggressive resource limits to keep your system usable while the build runs.
1616+1717+## Install
1818+1919+Either add to PATH:
2020+2121+```sh
2222+export PATH=$(pwd):$PATH
2323+```
2424+2525+Or symlink
2626+2727+```sh
2828+sudo ln -s $(pwd)/gentle.sh /usr/local/bin
2929+```
3030+3131+## Usage
3232+3333+```bash
3434+gentle.sh <command> [args...]
3535+```
3636+3737+## Resource Limits
3838+3939+The following resource controls are applied to all commands run through `gentle.sh`:
4040+4141+### CPU Limits
4242+4343+- **CPU Affinity**: All CPUs except the first 2 (keeps cores 0-1 free for system)
4444+- **CPU Scheduling Policy**: `batch` - lower priority than normal processes
4545+ - Available lower option: `idle` - only runs when nothing else needs CPU
4646+- **CPU Weight**: `1` - minimum weight (1-10000 range)
4747+- **CPU Quota Period**: `300ms` - period for quota measurement
4848+- **Nice Level**: `19` - lowest nice priority
4949+5050+### I/O Limits
5151+5252+- **IO Weight**: `1` - minimum weight (1-10000 range)
5353+- **IO Scheduling Class**: `best-effort` with priority `7` - lowest best-effort priority
5454+ - Available lower option: `idle` - lowest possible IO priority
5555+- **IO Device Latency**: `infinity` applied to all detected block devices - no strict latency enforcement on any drive
5656+5757+### Memory Limits
5858+5959+- **MemoryMax**: `80%` - cap at 80% of system memory
6060+- **TasksMax**: `infinity` - unlimited processes
6161+6262+## Examples
6363+6464+Build a large project without freezing your system:
6565+6666+```bash
6767+gentle.sh make -j8
6868+```
6969+7070+Run a compilation:
7171+7272+```bash
7373+gentle.sh ./build.sh
7474+```
7575+7676+## Notes
7777+7878+- The script uses `systemd-run --scope --user`, which requires systemd user sessions
7979+- Block devices are auto-detected using `lsblk` and IO latency targets are set for all drives
8080+- The process runs in the foreground (not detached as a service)
8181+- All resource limits are applied to the process and its children
+40
gentle.sh
···11+#!/bin/bash
22+33+# Run a command gently with limited CPU, IO, and nice values using systemd-run
44+55+# Calculate CPU affinity (all CPUs except first 2)
66+CPU_COUNT=$(nproc)
77+CPU_AFFINITY="2-$(($CPU_COUNT - 1))"
88+99+# Get all base block devices to set IO latency target on all drives
1010+BLOCK_DEVICES=$(lsblk -d -n -o NAME | grep -E "^(nvme|sd)")
1111+1212+# Build systemd-run command
1313+# Note: IOSchedulingClass=idle is even lower priority than best-effort
1414+# Note: CPUSchedulingPolicy=idle is even lower priority than batch
1515+RUN_CMD=(
1616+ systemd-run
1717+ --scope
1818+ --user
1919+ --nice=19
2020+ --io-weight=1
2121+ --cpu-affinity="$CPU_AFFINITY"
2222+ --property=CPUWeight=1
2323+ --property=MemoryMax=80%
2424+ --property=TasksMax=infinity
2525+ --property=CPUQuotaPeriodSec=300ms
2626+ --property=IOSchedulingClass=best-effort
2727+ --property=IOSchedulingPriority=7
2828+ --property=CPUSchedulingPolicy=batch
2929+)
3030+3131+# Add IODeviceLatencyTargetSec for each block device
3232+for device in $BLOCK_DEVICES; do
3333+ RUN_CMD+=("--property=IODeviceLatencyTargetSec=/dev/$device 20s")
3434+done
3535+3636+# Add the command to run
3737+RUN_CMD+=("$@")
3838+3939+# Execute
4040+"${RUN_CMD[@]}"