mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 16:44:23 +08:00
🏅 Sync 2026-07-25 20:22:21
This commit is contained in:
1 parent
9c077adbc3
commit
db661eb60a
19 files changed
+1051
-118
No files matched your search
+1
-1
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qosmate
|
||||
PKG_VERSION:=0.5.48
|
||||
PKG_RELEASE:=3
|
||||
PKG_RELEASE:=4
|
||||
|
||||
PKG_MAINTAINER:=Markus Hütter <mh@hudra.net>
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
|
||||
+8
-22
@@ -377,6 +377,8 @@ logread | grep qosmate-autorate
|
||||
|
||||
QoSmate allows you to define custom DSCP (Differentiated Services Code Point) marking rules to prioritize specific types of traffic. These rules are defined in the `/etc/config/qosmate` file under the `rule` sections and via luci-app-qosmate.
|
||||
|
||||
> **Rules are only evaluated in the upload direction.** QoSmate stores the DSCP of a connection in conntrack on egress, and `tc-ctinfo` restores it on incoming packets before the firewall sees them. WAN → LAN traffic therefore bypasses rule evaluation completely. One rule that matches the upload direction (for example the `src_ip` of your device) automatically covers the download direction of the same connection. A mirrored "inbound" rule is not needed - it can never match, and its counter stays at 0.
|
||||
|
||||
| Config option | Description | Type | Default |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| name | A unique name for the rule. Used for identification and logging. | string | |
|
||||
@@ -424,50 +426,33 @@ config rule
|
||||
option class 'cs1'
|
||||
option counter '1'
|
||||
```
|
||||
Explanation: This rule assigns low priority to P2P traffic (like BitTorrent) by marking it as CS1. Using `list` for both `src_port` and `dest_port` covers both incoming and outgoing P2P traffic.
|
||||
Explanation: This rule assigns low priority to P2P traffic (like BitTorrent) by marking it as CS1. Both port lists are matched on outgoing packets: `src_port` catches traffic sent from your local peer's listening port, `dest_port` catches traffic sent to a remote peer's listening port.
|
||||
|
||||
3. Call of Duty Game Traffic:
|
||||
```
|
||||
config rule
|
||||
option name 'cod1'
|
||||
option name 'cod'
|
||||
option proto 'udp'
|
||||
option src_ip '192.168.1.208'
|
||||
option src_port '3074'
|
||||
option dest_port '30000-65535'
|
||||
option class 'cs5'
|
||||
option counter '1'
|
||||
|
||||
config rule
|
||||
option name 'cod2'
|
||||
option proto 'udp'
|
||||
option dest_ip '192.168.1.208'
|
||||
option dest_port '3074'
|
||||
option class 'cs5'
|
||||
option counter '1'
|
||||
```
|
||||
Explanation: These rules prioritize Call of Duty game traffic. The first rule targets outgoing traffic from the game console (IP 192.168.1.208), while the second rule handles incoming traffic. Both use CS5 class, which is typically used for gaming traffic due to its high priority. The wide range of destination ports in the first rule covers the game's server ports.
|
||||
Explanation: This rule prioritizes Call of Duty game traffic sent by the console (IP 192.168.1.208) from port 3074 to the game's server ports. It uses the CS5 class, which is typically used for gaming traffic due to its high priority. The incoming traffic of these connections is handled automatically via conntrack, so a second rule for the download direction is not required.
|
||||
|
||||
4. Generic Game Console/Gaming PC Traffic:
|
||||
```
|
||||
config rule
|
||||
option name 'Game_Console_Outbound'
|
||||
option name 'Game_Console'
|
||||
option proto 'udp'
|
||||
option src_ip '192.168.1.208'
|
||||
list dest_port '!=80'
|
||||
list dest_port '!=443'
|
||||
option class 'cs5'
|
||||
option counter '1'
|
||||
|
||||
config rule
|
||||
option name 'Game_Console_Inbound'
|
||||
option proto 'udp'
|
||||
option dest_ip '192.168.1.208'
|
||||
list src_port '!=80'
|
||||
list src_port '!=443'
|
||||
option class 'cs5'
|
||||
option counter '1'
|
||||
```
|
||||
Explanation: These rules provide a more generic approach to prioritizing game console/gaming pc traffic. The outbound rule prioritizes all UDP traffic from the console (192.168.1.208) except for ports 80 and 443 (common web traffic). The inbound rule does the same for incoming traffic. This approach ensures that game-related traffic gets priority while allowing normal web browsing to use default priorities. The use of '!=' (not equal) in the port lists demonstrates how to exclude specific ports from the rule.
|
||||
Explanation: This rule provides a more generic approach to prioritizing game console/gaming pc traffic. It prioritizes all UDP traffic from the console (192.168.1.208) except for ports 80 and 443 (common web traffic), which ensures that game-related traffic gets priority while allowing normal web browsing to use default priorities. The use of '!=' (not equal) in the port list demonstrates how to exclude specific ports from the rule.
|
||||
This is more or less equivalent to the `realtime4` and `realtime6` variables from the SimpleHFSCgamer script. However, this rule is even better as it excludes UDP port 80 and 443, which are often used for QUIC. This is likely less of an issue on a gaming console than on a gaming PC, where a YouTube video using QUIC might be running alongside the game.
|
||||
|
||||
This rule is also applied when the auto-setup is used via CLI or UI and a Gaming Device IP (optional) is entered.
|
||||
@@ -1453,6 +1438,7 @@ QoSmate handles traffic in both directions (upload and download) using the follo
|
||||
- If the conditional bit (128) is set, the original DSCP value is restored:
|
||||
- DSCP is extracted as `mark & 63`
|
||||
- This DSCP value is applied to incoming packets
|
||||
- Since the DSCP is already restored at this point, WAN → LAN packets skip the nftables marking chain, which is why rule counters only increase for the upload direction
|
||||
|
||||
3. **IFB (Intermediate Functional Block):**
|
||||
- Linux can only shape outgoing traffic
|
||||
|
||||
@@ -83,6 +83,10 @@ config autorate 'autorate'
|
||||
option flash_history '0'
|
||||
option log_changes '0'
|
||||
|
||||
# Rules are only evaluated on egress (LAN -> WAN): QoSmate stores the DSCP in conntrack
|
||||
# and tc-ctinfo restores it on ingress. One rule matching the upload direction therefore
|
||||
# covers both directions of a connection - a mirrored inbound rule would never match.
|
||||
|
||||
#config rule 'cod1'
|
||||
# option name 'cod1'
|
||||
# option proto 'udp'
|
||||
@@ -92,14 +96,6 @@ config autorate 'autorate'
|
||||
# option class 'cs5'
|
||||
# option counter '1'
|
||||
|
||||
#config rule 'cod2'
|
||||
# option name 'cod3'
|
||||
# option proto 'udp'
|
||||
# option dest_ip '192.168.1.208'
|
||||
# option dest_port '3074'
|
||||
# option class 'cs5'
|
||||
# option counter '1'
|
||||
|
||||
#config rule
|
||||
# option name 'TeamViewer'
|
||||
# option proto 'tcp'
|
||||
@@ -109,17 +105,11 @@ config autorate 'autorate'
|
||||
# option counter '1'
|
||||
|
||||
#config rule
|
||||
# option name 'ServerDownPrio1'
|
||||
# option name 'ServerDownPrio'
|
||||
# option src_ip '192.168.15.0/24'
|
||||
# option class 'cs1'
|
||||
# option counter '1'
|
||||
|
||||
#config rule
|
||||
# option name 'ServerDownPrio2'
|
||||
# option dest_ip '192.168.15.0/24'
|
||||
# option class 'cs1'
|
||||
# option counter '1'
|
||||
|
||||
#config ipset
|
||||
# option name 'gaming_devices'
|
||||
# option mode 'static'
|
||||
|
||||
+135
-45
@@ -9,12 +9,13 @@ USE_PROCD=1
|
||||
VERSION="dev"
|
||||
UPD_CHANNEL="release"
|
||||
|
||||
EXTRA_COMMANDS="check_version update auto_setup auto_setup_noninteractive validate_custom_rules health_check"
|
||||
EXTRA_COMMANDS="check_version update auto_setup auto_setup_noninteractive auto_setup_detached validate_custom_rules health_check"
|
||||
EXTRA_HELP="
|
||||
check_version Check for updates
|
||||
update Update qosmate
|
||||
auto_setup Automatically configure qosmate
|
||||
auto_setup_noninteractive Automatically configure qosmate with no interaction
|
||||
auto_setup_detached Start the non-interactive auto-setup in the background
|
||||
validate_custom_rules Validate custom rules
|
||||
health_check Check if QoSmate is properly configured and running"
|
||||
|
||||
@@ -54,6 +55,7 @@ QOSMATE_DEFAULTS_FILE=${QOSMATE_D}/qosmate-defaults
|
||||
QOSMATE_CUSTOM_RULES_FILE=${QOSMATE_D}/custom_rules.nft
|
||||
QOSMATE_INLINE_RULES_FILE=${QOSMATE_D}/inline_dscptag.nft
|
||||
QOSMATE_RUN_DIR=/tmp/qosmate
|
||||
QOSMATE_AUTO_SETUP_OUTPUT=/tmp/qosmate_auto_setup_output.txt
|
||||
|
||||
# Local path of JS files
|
||||
QOSMATE_UPD_DIR=/var/run/qosmate-update
|
||||
@@ -197,7 +199,7 @@ print_msg() {
|
||||
# logs each argument separately and prints to a separate line
|
||||
# optional arguments: '-err', '-warn' to set logged error level
|
||||
log_msg() {
|
||||
local msgs_prefix='' _arg err_l=info msgs_dest
|
||||
local msgs_prefix='' _arg err_l=info
|
||||
|
||||
local IFS="$DEFAULT_IFS"
|
||||
for _arg in "$@"
|
||||
@@ -207,11 +209,12 @@ log_msg() {
|
||||
"-warn") err_l=warn msgs_prefix="Warning: " ;;
|
||||
'') printf '\n' ;; # print out empty lines
|
||||
*)
|
||||
# Write to the inherited descriptors instead of redirecting to /dev/stdout: that
|
||||
# re-opens the target, and when stdout is a regular file '>' truncates it.
|
||||
case "$err_l" in
|
||||
err|warn) msgs_dest="/dev/stderr" ;;
|
||||
*) msgs_dest="/dev/stdout"
|
||||
err|warn) printf '%s\n' "${msgs_prefix}${_arg}" >&2 ;;
|
||||
*) printf '%s\n' "${msgs_prefix}${_arg}"
|
||||
esac
|
||||
printf '%s\n' "${msgs_prefix}${_arg}" > "$msgs_dest"
|
||||
logger -t qosmate -p user."$err_l" "${msgs_prefix}${_arg}"
|
||||
msgs_prefix=''
|
||||
esac
|
||||
@@ -2218,6 +2221,48 @@ parse_speedtest_output() {
|
||||
:
|
||||
}
|
||||
|
||||
# Prints WAN throughput in Mbit/s once per second as "<rx> <tx>", until killed.
|
||||
# 1 - network device
|
||||
sample_wan_rates() {
|
||||
local stats="/sys/class/net/${1}/statistics" prev_rx prev_tx rx tx
|
||||
read -r prev_rx < "$stats/rx_bytes" && read -r prev_tx < "$stats/tx_bytes" || return 1
|
||||
while sleep 1; do
|
||||
read -r rx < "$stats/rx_bytes" && read -r tx < "$stats/tx_bytes" || return 1
|
||||
printf '%s %s\n' $(( (rx - prev_rx) * 8 / 1000000 )) $(( (tx - prev_tx) * 8 / 1000000 ))
|
||||
prev_rx=$rx prev_tx=$tx
|
||||
done
|
||||
}
|
||||
|
||||
# Median of the samples reaching at least half of the peak sample, which is the plateau of a test
|
||||
# phase. Ignores ramp-up, idle time and the ACK traffic of the opposite direction.
|
||||
# Prints 0 if there is no usable plateau.
|
||||
# 1 - samples file, 2 - column (1 = rx, 2 = tx)
|
||||
plateau_rate() {
|
||||
[ -s "$1" ] || { echo "0"; return 0; }
|
||||
awk -v col="$2" '
|
||||
{ v[NR] = $col + 0; if (v[NR] > peak) peak = v[NR] }
|
||||
END {
|
||||
if (peak <= 0) { print 0; exit }
|
||||
for (i = 1; i <= NR; i++) if (v[i] >= peak / 2) s[++n] = v[i]
|
||||
if (n < 3) { print 0; exit }
|
||||
for (i = 2; i <= n; i++) { x = s[i]; for (j = i - 1; j > 0 && s[j] > x; j--) s[j + 1] = s[j]; s[j + 1] = x }
|
||||
print (n % 2) ? s[(n + 1) / 2] : int((s[n / 2] + s[n / 2 + 1]) / 2)
|
||||
}' "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
# 1, 2 - rates to compare
|
||||
lower_of() {
|
||||
awk -v a="$1" -v b="$2" 'BEGIN{print (a < b) ? a : b}'
|
||||
}
|
||||
|
||||
# Warns when the speed test result is implausibly higher than what crossed the interface.
|
||||
# 1 - direction label, 2 - reported rate, 3 - measured rate
|
||||
warn_if_overreported() {
|
||||
awk -v r="$2" -v m="$3" 'BEGIN{exit !(m > 0 && r > m * 1.25)}' &&
|
||||
print_msg "Warning: the speed test reported $2 Mbit/s $1, but only $3 Mbit/s crossed the WAN interface. Using the measured value."
|
||||
:
|
||||
}
|
||||
|
||||
auto_setup() {
|
||||
try_auto_setup "$@" && return 0
|
||||
error_out "auto-setup failed."
|
||||
@@ -2380,15 +2425,49 @@ try_auto_setup() {
|
||||
fi
|
||||
|
||||
print_msg "Running speed test... This may take a few minutes."
|
||||
SPEED_RESULT=$($SPEEDTEST_CMD)
|
||||
|
||||
DOWNLOAD_SPEED=$(printf %s "$SPEED_RESULT" | parse_speedtest_output "$SPEEDTEST_CMD" Download) &&
|
||||
UPLOAD_SPEED=$(printf %s "$SPEED_RESULT" | parse_speedtest_output "$SPEEDTEST_CMD" Upload) ||
|
||||
return 1
|
||||
local samples_file=/tmp/qosmate-speedtest-samples sampler_pid speedtest_rv retried=''
|
||||
local reported_down reported_up measured_down measured_up
|
||||
|
||||
while :; do
|
||||
sample_wan_rates "$FINAL_INTERFACE" > "$samples_file" &
|
||||
sampler_pid=$!
|
||||
SPEED_RESULT=$($SPEEDTEST_CMD 2>&1)
|
||||
speedtest_rv=$?
|
||||
kill "$sampler_pid" 2>/dev/null
|
||||
|
||||
[ "$speedtest_rv" = 0 ] &&
|
||||
DOWNLOAD_SPEED=$(printf %s "$SPEED_RESULT" | parse_speedtest_output "$SPEEDTEST_CMD" Download) &&
|
||||
UPLOAD_SPEED=$(printf %s "$SPEED_RESULT" | parse_speedtest_output "$SPEEDTEST_CMD" Upload) &&
|
||||
break
|
||||
|
||||
[ -z "$retried" ] || {
|
||||
# include the tool output, otherwise the failure is only reported generically
|
||||
error_out "Speed test failed (exit code $speedtest_rv). Speed test output:" "$SPEED_RESULT"
|
||||
return 1
|
||||
}
|
||||
retried=1
|
||||
log_msg -warn "Speed test failed (exit code $speedtest_rv), retrying once."
|
||||
done
|
||||
|
||||
# A speed test measures at the socket, so it can report several times the rate that actually
|
||||
# crossed the link (speedtest-go does this on upload). Cross-check with the WAN counters.
|
||||
reported_down="$DOWNLOAD_SPEED" reported_up="$UPLOAD_SPEED"
|
||||
measured_down=$(plateau_rate "$samples_file" 1)
|
||||
measured_up=$(plateau_rate "$samples_file" 2)
|
||||
rm -f "$samples_file"
|
||||
|
||||
# Use the lower value: the test may over-report, the counters may include foreign traffic
|
||||
[ "$measured_down" != 0 ] && DOWNLOAD_SPEED=$(lower_of "$reported_down" "$measured_down")
|
||||
[ "$measured_up" != 0 ] && UPLOAD_SPEED=$(lower_of "$reported_up" "$measured_up")
|
||||
|
||||
warn_if_overreported download "$reported_down" "$measured_down"
|
||||
warn_if_overreported upload "$reported_up" "$measured_up"
|
||||
|
||||
print_msg "Speed test results:" \
|
||||
"Download speed: $DOWNLOAD_SPEED Mbit/s" \
|
||||
"Upload speed: $UPLOAD_SPEED Mbit/s"
|
||||
"Upload speed: $UPLOAD_SPEED Mbit/s" \
|
||||
"WAN counters during the test: $measured_down Mbit/s down, $measured_up Mbit/s up (speed test: $reported_down / $reported_up)"
|
||||
fi
|
||||
|
||||
# Convert speeds to kbps and apply 90% rule
|
||||
@@ -2419,43 +2498,29 @@ try_auto_setup() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$gaming_ip" ]; then
|
||||
# Validate IP address format
|
||||
if [[ $gaming_ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
# Check if rules for this IP already exist
|
||||
local ip_configured=
|
||||
config_foreach is_ip_configured rule "$gaming_ip"
|
||||
# $ip_configured is set in is_ip_configured()
|
||||
if [ -n "$ip_configured" ]; then
|
||||
print_msg "Rules for IP $gaming_ip already exist. Skipping addition of new rules."
|
||||
gaming_ip=
|
||||
fi
|
||||
# Exactly one outcome is reported, so the UI can always tell the user what happened
|
||||
local ip_configured=
|
||||
if [ -z "$gaming_ip" ]; then
|
||||
print_msg "No gaming device IP given - no rule added."
|
||||
elif [[ ! "$gaming_ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
print_msg "Invalid IP address format '$gaming_ip' - no gaming device rule added."
|
||||
else
|
||||
config_foreach is_ip_configured rule "$gaming_ip" # sets $ip_configured
|
||||
if [ -n "$ip_configured" ]; then
|
||||
print_msg "A rule for IP $gaming_ip already exists - keeping it."
|
||||
else
|
||||
print_msg "Invalid IP address format. No gaming device rules added."
|
||||
gaming_ip=
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$gaming_ip" ]; then
|
||||
local direction ip_dir port_dir
|
||||
for direction in Inbound Outbound; do
|
||||
case "$direction" in
|
||||
Inbound) ip_dir=dest port_dir=src ;;
|
||||
Outbound) ip_dir=src port_dir=dest ;;
|
||||
esac
|
||||
# Only an egress rule is needed: the DSCP is stored in conntrack and restored on ingress via tc-ctinfo
|
||||
uci add qosmate rule 1>/dev/null &&
|
||||
uci set "qosmate.@rule[-1].name=Game_Console_${direction}" &&
|
||||
uci set "qosmate.@rule[-1].name=Game_Console" &&
|
||||
uci set "qosmate.@rule[-1].proto=udp" &&
|
||||
uci set "qosmate.@rule[-1].${ip_dir}_ip=${gaming_ip}" &&
|
||||
uci add_list "qosmate.@rule[-1].${port_dir}_port=!=80" &&
|
||||
uci add_list "qosmate.@rule[-1].${port_dir}_port=!=443" &&
|
||||
uci set "qosmate.@rule[-1].src_ip=${gaming_ip}" &&
|
||||
uci add_list "qosmate.@rule[-1].dest_port=!=80" &&
|
||||
uci add_list "qosmate.@rule[-1].dest_port=!=443" &&
|
||||
uci set "qosmate.@rule[-1].class=cs5" &&
|
||||
uci set "qosmate.@rule[-1].counter=1" ||
|
||||
return 1
|
||||
done
|
||||
print_msg "Gaming device rules added for IP: $gaming_ip"
|
||||
else
|
||||
print_msg "No gaming device IP added."
|
||||
print_msg "Gaming device rule added for IP: $gaming_ip"
|
||||
fi
|
||||
fi
|
||||
|
||||
uci commit qosmate || return 1
|
||||
@@ -2470,16 +2535,41 @@ try_auto_setup() {
|
||||
}
|
||||
|
||||
auto_setup_noninteractive() {
|
||||
local output_file="/tmp/qosmate_auto_setup_output.txt" auto_setup_rv
|
||||
local auto_setup_rv
|
||||
# Truncate up front and append afterwards. Truncating while a writer already holds an offset
|
||||
# leaves a gap that the kernel fills with NUL bytes, and ubus file.read stops at the first NUL,
|
||||
# so a polling caller would only ever see the beginning of the file.
|
||||
: > "$QOSMATE_AUTO_SETUP_OUTPUT"
|
||||
{
|
||||
echo "Starting qosmate non-interactive auto-setup..."
|
||||
auto_setup -n "$1" 2>&1
|
||||
} > "$output_file"
|
||||
auto_setup_rv=$?
|
||||
echo "$output_file"
|
||||
auto_setup_rv=$?
|
||||
# lets callers polling this file tell a finished run from a partial or stale one
|
||||
echo "AUTO_SETUP_DONE rv=$auto_setup_rv"
|
||||
} >> "$QOSMATE_AUTO_SETUP_OUTPUT"
|
||||
echo "$QOSMATE_AUTO_SETUP_OUTPUT"
|
||||
return $auto_setup_rv
|
||||
}
|
||||
|
||||
# Starts the non-interactive auto-setup detached and prints the output file path right away.
|
||||
# A speed test regularly takes longer than uhttpd's script_timeout (60s by default), which kills
|
||||
# the CGI and leaves the caller with a half-written file, so the caller polls the file instead.
|
||||
# 1 - optional gaming device IP
|
||||
auto_setup_detached() {
|
||||
printf '%s\n' "Starting qosmate auto-setup..." > "$QOSMATE_AUTO_SETUP_OUTPUT" || return 1
|
||||
# A new session is required, not just a background job: ash waits for children of the same
|
||||
# session in a command substitution, which is how callers read this function's output.
|
||||
if check_util setsid; then
|
||||
# stdin is closed as well, otherwise the run keeps the caller's pipe open - for a request
|
||||
# from the web UI that blocks the connection the UI then polls on
|
||||
setsid "$QOSMATE_SERVICE_PATH" auto_setup_noninteractive "$1" >/dev/null 2>&1 <&- &
|
||||
else
|
||||
log_msg -warn "setsid is not available, running the auto-setup in the foreground."
|
||||
auto_setup_noninteractive "$1" >/dev/null 2>&1
|
||||
fi
|
||||
echo "$QOSMATE_AUTO_SETUP_OUTPUT"
|
||||
}
|
||||
|
||||
health_check() {
|
||||
# Check if QoSmate is properly configured and running
|
||||
local status="" errors=0 service_enabled=0 config_status=''
|
||||
|
||||
+13
-8
@@ -25,15 +25,21 @@ error_out() { log_msg -err "${@}"; }
|
||||
|
||||
# prints each argument to a separate line
|
||||
print_msg() {
|
||||
local _arg msgs_dest="/dev/stdout" msgs_prefix=''
|
||||
# Write to the inherited descriptors instead of redirecting to /dev/stdout: that re-opens the
|
||||
# target, and when stdout is a regular file '>' truncates it.
|
||||
local _arg to_stderr='' msgs_prefix=''
|
||||
for _arg in "$@"
|
||||
do
|
||||
case "${_arg}" in
|
||||
-err) msgs_dest="/dev/stderr" msgs_prefix="Error: " ;;
|
||||
-warn) msgs_dest="/dev/stderr" msgs_prefix="Warning: " ;;
|
||||
-err) to_stderr=1 msgs_prefix="Error: " ;;
|
||||
-warn) to_stderr=1 msgs_prefix="Warning: " ;;
|
||||
'') printf '\n' ;; # print out empty lines
|
||||
*)
|
||||
printf '%s\n' "${msgs_prefix}${_arg}" > "$msgs_dest"
|
||||
if [ -n "$to_stderr" ]; then
|
||||
printf '%s\n' "${msgs_prefix}${_arg}" >&2
|
||||
else
|
||||
printf '%s\n' "${msgs_prefix}${_arg}"
|
||||
fi
|
||||
msgs_prefix=''
|
||||
esac
|
||||
done
|
||||
@@ -43,7 +49,7 @@ print_msg() {
|
||||
# logs each argument separately and prints to a separate line
|
||||
# optional arguments: '-err', '-warn' to set logged error level
|
||||
log_msg() {
|
||||
local msgs_prefix='' _arg err_l=info msgs_dest
|
||||
local msgs_prefix='' _arg err_l=info
|
||||
|
||||
local IFS="$DEFAULT_IFS"
|
||||
for _arg in "$@"
|
||||
@@ -54,10 +60,9 @@ log_msg() {
|
||||
'') printf '\n' ;; # print out empty lines
|
||||
*)
|
||||
case "$err_l" in
|
||||
err|warn) msgs_dest="/dev/stderr" ;;
|
||||
*) msgs_dest="/dev/stdout"
|
||||
err|warn) printf '%s\n' "${msgs_prefix}${_arg}" >&2 ;;
|
||||
*) printf '%s\n' "${msgs_prefix}${_arg}"
|
||||
esac
|
||||
printf '%s\n' "${msgs_prefix}${_arg}" > "$msgs_dest"
|
||||
logger -t qosmate -p user."$err_l" "${msgs_prefix}${_arg}"
|
||||
msgs_prefix=''
|
||||
esac
|
||||
|
||||
Reference in new issue
Block a user