r_bash | Unsorted

Telegram-канал r_bash - r_bash

36

Credits: @r_channels & @reddit2telegram

Subscribe to a channel

r_bash

Proper terminal settings

I am writing a terminal emulator in go, for some reason when pressing enter on a prompt with no command (just the $ sign) bash doesn't send a \\n... is it up to my terminal to manage that?
Edit: after some more testing:

dev@arch:~ ls<output of command>\n
dev@arch:~

even after typing a command, bash doesn't send a \\n
Edit 2: after even more testing, this happens on every value for $TERM except dumb. If $TERM=dumb bash sends \\n

https://redd.it/1hci742
@r_bash

Читать полностью…

r_bash

Help message annotations

I had an idea to automatically create help messages for commands inside of a bash script. I wrote a quick script for personal use and was wondering what other people thought.

#!/usr/bin/env bash

HELP_MESSAGE_SPACING=35

# Generates help message given a function name
__help() {
help=$(declare -f $1 | awk '
NR>2 {
if ( $1 != ":") {
exit 0
} else if ($2 == "@help" ) {
for(i = 3; i < NF; i++){
printf "%s ", $i
}
printf "%s ", substr($NF, 1, length($NF)-1)
}
}')
printf "%-${HELP_MESSAGE_SPACING}s %s\n" "$1" "$help"
}

# User defined functions start here
# -------------------------------

function command_1 {
: u/help Example help message here
echo "Command 1"
}

function command_2 {
: @help Example help message here
echo "Command 2"
}


# User defined functions end here
#---------------------------------

if [[ $# == 0 ]]; then
cmds=$(compgen -A function | sed /^__*/d)
__printf "\033[31mError! No Command Selected!\033[0m\nRun Script Using sudo -E $0 <cmd> [args]\n\n\033[32mCommands:\033[0m\n"
for cmd in ${cmds[@]}; do
__help $cmd
done
else
CMD=$1
shift
if [[ $(type -t $CMD) == "function" ]]; then
$CMD $@
else
__printf "\033[31m$CMD is not a valid command!\033[0m\n";
fi
fi


Then running the script directly will generate a summary of each user defined function and `<script> command_1 [additional args here]` will run the bash code inside command\_1

https://redd.it/1hc8d8w
@r_bash

Читать полностью…

r_bash

trap inside or outside su subshell?

If I want to prevent Ctrl-C from interrupting the command I'm going to run in the terminal with su - -c, should I do

su - -c 'trap "" INT; somecommand'

or

trap '' INT; su - -c 'some
command'; trap - INT

Is there a difference in their functionality?

https://redd.it/1hb965x
@r_bash

Читать полностью…

r_bash

client configurations..." for CLIENT_FILE in "${DEVICE_CONFIG_DIR}"/*.conf; do local CLIENT_KEY=$(grep -Po '(?<=PublicKey = )[^\s]+' "${CLIENT_FILE}") if [[ ! " ${WG_PUBLIC_KEYS[*]} " =~ " ${CLIENT_KEY} " ]]; then echo "Orphaned client configuration detected: ${CLIENT_FILE}" rm -f "${CLIENT_FILE}" "${CLIENT_FILE}.png" echo "Removed orphaned client configuration: ${CLIENT_FILE}" fi done echo "Orphaned client configurations cleanup completed." } # Show QR Code for a client show_qr_code() { echo "------------------------------------" echo " Display QR Code for Client " echo "------------------------------------" # Get the list of available clients local CLIENTS=($(ls -1 "${DEVICE_CONFIG_DIR}" 2>/dev/null | sed 's/.conf$//')) if [[ ${#CLIENTS[@]} -eq 0 ]]; then echo "No clients available." return fi # Display the list of clients echo "Available Clients:" for i in "${!CLIENTS[@]}"; do echo "$((i + 1)). ${CLIENTS[$i]}" done # Prompt user to select a client read -p "Enter the number of the client to display QR code for: " CLIENT_INDEX if [[ ! "$CLIENT_INDEX" =~ ^[0-9]+$ ]] || (( CLIENT_INDEX < 1 || CLIENT_INDEX > ${#CLIENTS[@]} )); then echo "Invalid selection. Aborting." return fi # Identify the client configuration file local CLIENT_NAME="${CLIENTS[$((CLIENT_INDEX - 1))]}" local CLIENT_CONF_FILE="${DEVICE_CONFIG_DIR}/${CLIENT_NAME}.conf" if [[ ! -f "${CLIENT_CONF_FILE}" ]]; then echo "Error: Configuration file for '${CLIENT_NAME}' not found." return fi # Generate and display the QR code if command -v qrencode &>/dev/null; then qrencode -t ANSIUTF8 < "${CLIENT_CONF_FILE}" else echo "Error: 'qrencode' is not installed. Install it to display QR codes." fi } # Function to edit configurations edit_configuration() { echo "------------------------------------" echo " Edit Configuration " echo "------------------------------------" echo "1. Edit Server Configuration (wg0.conf)" echo "2. Edit a Client Configuration" read -p "Choose an option: " EDIT_OPTION case $EDIT_OPTION in 1) echo "Opening server configuration in micro..." micro "${WG_CONF_FILE}" ;; 2) echo "Available Clients:" local CLIENTS=($(ls -1 "${DEVICE_CONFIG_DIR}" 2>/dev/null | sed 's/.conf$//')) if [[ ${#CLIENTS[@]} -eq 0 ]]; then echo "No clients available to edit." return fi for i in "${!CLIENTS[@]}"; do echo "$((i + 1)). ${CLIENTS[$i]}" done read -p "Enter the number of the client to edit: " CLIENT_INDEX if [[ ! "$CLIENT_INDEX" =~ ^[0-9]+$ ]] || (( CLIENT_INDEX < 1 || CLIENT_INDEX > ${#CLIENTS[@]} )); then echo "Invalid selection. Aborting." return fi local CLIENT_NAME="${CLIENTS[$((CLIENT_INDEX - 1))]}" local CLIENT_CONF_FILE="${DEVICE_CONFIG_DIR}/${CLIENT_NAME}.conf" if [[ -f "${CLIENT_CONF_FILE}" ]]; then echo "Opening client configuration for '${CLIENT_NAME}' in micro..." micro "${CLIENT_CONF_FILE}" else echo "Error: Configuration file for '${CLIENT_NAME}' not found." fi ;; *) echo "Invalid option. Returning to main menu." ;; esac } # List clients list_clients() { echo "------------------------------------" echo " Configured Clients " echo "------------------------------------" local CLIENTS=($(ls -1 "${DEVICE_CONFIG_DIR}" 2>/dev/null | sed 's/.conf$//')) if [[ ${#CLIENTS[@]} -eq 0 ]]; then echo "No clients configured." return fi for i in "${!CLIENTS[@]}"; do echo "$((i + 1)). ${CLIENTS[$i]}" done } # Main menu while true; do echo "------------------------------------" echo " WireGuard Management " echo "------------------------------------" echo "1. Add Client" echo "2. Remove Client" echo "3. List Clients" echo "4. Edit Configuration" echo "5. Display Server Configuration" echo "6. Clean Up wg0.conf" echo "7. Show QR Code for Client" echo "8. Clean Up Orphaned Client Configs" echo "9. Exit" echo "------------------------------------" read -p "Choose an option: " OPTION case $OPTION in 1) read -p "Enter client name: " CLIENT_NAME read -p "Tunnel mode (full/split): " TUNNEL_MODE backup_config add_client "${CLIENT_NAME}" "${TUNNEL_MODE}" ;; 2) backup_config remove_client ;; 3) list_clients ;; 4) edit_configuration ;; 5) echo "Displaying server configuration..." cat

Читать полностью…

r_bash

${GENERATED_KEY}" "${WG_CONF_FILE}"; then return 1 fi # Check existing client configs for the PublicKey for CLIENT_FILE in "${DEVICE_CONFIG_DIR}"/*.conf; do if [[ -f "${CLIENT_FILE}" ]] && grep -q "PublicKey = ${GENERATED_KEY}" "${CLIENT_FILE}"; then return 1 fi done return 0 } # Securely generate unique keys local CLIENT_PRIVATE_KEY local CLIENT_PUBLIC_KEY while true; do # Securely create temporary files local CLIENT_PRIVATE_KEY_FILE local CLIENT_PUBLIC_KEY_FILE CLIENT_PRIVATE_KEY_FILE=$(mktemp -p /tmp client_privatekey_XXXXXX) CLIENT_PUBLIC_KEY_FILE=$(mktemp -p /tmp client_publickey_XXXXXX) # Generate the keys wg genkey > "${CLIENT_PRIVATE_KEY_FILE}" wg pubkey < "${CLIENT_PRIVATE_KEY_FILE}" > "${CLIENT_PUBLIC_KEY_FILE}" # Read keys into variables CLIENT_PRIVATE_KEY=$(<"${CLIENT_PRIVATE_KEY_FILE}") CLIENT_PUBLIC_KEY=$(<"${CLIENT_PUBLIC_KEY_FILE}") # Clean up temporary files securely shred -u "${CLIENT_PRIVATE_KEY_FILE}" "${CLIENT_PUBLIC_KEY_FILE}" # Ensure the PublicKey is unique if ensure_unique_public_key "${CLIENT_PUBLIC_KEY}"; then break else log ERROR "Duplicate PublicKey detected. Regenerating keys..." fi done log INFO "Generated secure keys for client '${CLIENT_NAME}'" log DEBUG "PublicKey: ${CLIENT_PUBLIC_KEY}" # Get the server's public key SERVER_PUBLIC_KEY=$(wg show wg0 public-key) if [[ -z "${SERVER_PUBLIC_KEY}" ]]; then log ERROR "Unable to retrieve the server's public key." exit 1 fi log DEBUG "Server public key retrieved." # Generate a unique IP for the client log INFO "Adding client '${CLIENT_NAME}' with tunnel mode '${TUNNEL_MODE}'" CLIENT_IP=$(generate_unique_client_ip) if [[ -z "${CLIENT_IP}" ]]; then log ERROR "Failed to generate a unique IP for the client." exit 1 fi log DEBUG "Generated Client IP: ${CLIENT_IP}" # Define AllowedIPs based on tunnel mode if [[ "${TUNNEL_MODE}" == "full" ]]; then CLIENT_ALLOWED_IPS="0.0.0.0/0,::/0" else CLIENT_ALLOWED_IPS="${FULL_SUBNET},${HOME_LAN_SUBNET}" fi log DEBUG "Allowed IPs set to ${CLIENT_ALLOWED_IPS}" # Create the client configuration CLIENT_CONF_FILE="${DEVICE_CONFIG_DIR}/${CLIENT_NAME}.conf" cat <<EOF >"${CLIENT_CONF_FILE}" [Interface] PrivateKey = ${CLIENT_PRIVATE_KEY} Address = ${CLIENT_IP} DNS = ${DEFAULT_DNS} [Peer] PublicKey = ${SERVER_PUBLIC_KEY} Endpoint = ${DEFAULT_ENDPOINT}:${SERVER_PORT} AllowedIPs = ${CLIENT_ALLOWED_IPS} EOF log INFO "Client configuration saved: ${CLIENT_CONF_FILE}" # Add the client to wg0.conf { echo "[Peer]" echo "PublicKey = ${CLIENT_PUBLIC_KEY}" echo "AllowedIPs = ${CLIENT_IP}" } >>"${WG_CONF_FILE}" log INFO "Client ${CLIENT_NAME} added to WireGuard configuration." # Restart WireGuard restart_wireguard } # Secure Log File setup_log_rotation() { cat <<EOF > /etc/logrotate.d/wireguard ${LOG_FILE} { daily rotate 7 compress missingok notifempty create 600 root root } EOF echo "Log rotation configured." } # Restrict log file permissions chmod 600 "${LOG_FILE}" # List clients list_clients() { echo "Configured Clients:" grep -A 2 "\[Peer\]" "${WG_CONF_FILE}" | awk ' /PublicKey/ {public_key=$3} /AllowedIPs/ {allowed_ips=$3; print "Client Public Key: " public_key "\nAllowed IPs: " allowed_ips "\n"} ' } # Remove a client remove_client() { echo "------------------------------------" echo " Remove WireGuard Client " echo "------------------------------------" # List available clients local CLIENTS=($(ls -1 "${DEVICE_CONFIG_DIR}" 2>/dev/null | sed 's/.conf$//')) if [[ ${#CLIENTS[@]} -eq 0 ]]; then echo "No clients available to remove." return fi echo "Available Clients:" for i in "${!CLIENTS[@]}"; do echo "$((i + 1)). ${CLIENTS[$i]}" done # Prompt for client selection read -p "Enter the number of the client to remove: " CLIENT_INDEX if [[ ! "$CLIENT_INDEX" =~ ^[0-9]+$ ]] || (( CLIENT_INDEX < 1 || CLIENT_INDEX > ${#CLIENTS[@]} )); then echo "Invalid selection. Aborting." return fi local CLIENT_NAME="${CLIENTS[$((CLIENT_INDEX - 1))]}" local CLIENT_CONF_FILE="${DEVICE_CONFIG_DIR}/${CLIENT_NAME}.conf" # Ensure the client configuration file exists if [[ ! -f "${CLIENT_CONF_FILE}" ]]; then echo "Error: Configuration file for '${CLIENT_NAME}'

Читать полностью…

r_bash

^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then echo "Error: ${error_message:-Invalid DNS format. Use a valid IP (e.g., 10.6.0.7).}" return 1 fi ;; port) if ! [[ "$value" =~ ^[0-9]+$ ]] || (( value < 1 || value > 65535 )); then echo "Error: ${error_message:-Invalid port. Use a number between 1 and 65535.}" return 1 fi ;; client-name) if ! [[ "$value" =~ ^[a-zA-Z0-9_-]+$ ]]; then echo "Error: ${error_message:-Client name can only include letters, numbers, dashes, and underscores.}" return 1 fi ;; *) echo "Error: Unknown validation type '$type'." return 1 ;; esac return 0 } # Prompt for user inputs and validate read -p "Enter your home LAN subnet (default: 10.6.0.0/24): " INPUT_HOME_LAN_SUBNET HOME_LAN_SUBNET="${INPUT_HOME_LAN_SUBNET:-10.6.0.0/24}" read -p "Enter WireGuard Server IP (e.g., 10.100.0.1/24): " INPUT_SERVER_IP SERVER_IP="${INPUT_SERVER_IP:-10.100.0.1/24}" read -p "Enter WireGuard port (default: 51642): " INPUT_SERVER_PORT SERVER_PORT="${INPUT_SERVER_PORT:-51642}" read -p "Enter Pi-hole DNS IP (default: 10.6.0.7): " INPUT_DNS DEFAULT_DNS="${INPUT_DNS:-10.6.0.7}" # Derived values SUBNET="${SERVER_IP##*/}" # Extract the CIDR part (e.g., 24) SUBNET_PREFIX="${SERVER_IP%/*}" # Extract the IP prefix (e.g., 10.100.0.1) FULL_SUBNET="${SUBNET_PREFIX%.*}.0/${SUBNET}" # Build full subnet (e.g., 10.100.0.0/24) #Validate Tunnel Mode validate_tunnel_mode() { local MODE=$1 if [[ "${MODE}" != "full" && "${MODE}" != "split" ]]; then echo "Error: Invalid tunnel mode. Choose 'full' or 'split'." exit 1 fi } # Validate Inputs if ! validate "$SERVER_IP" "ip" "Invalid IP address format. Use CIDR notation (e.g., 10.100.0.1/24)."; then exit 1 fi if ! validate "$HOME_LAN_SUBNET" "ip" "Invalid subnet format. Use CIDR notation (e.g., 10.6.0.0/24)."; then exit 1 fi if ! validate "$SERVER_PORT" "port" "Invalid port number. Use a value between 1 and 65535."; then exit 1 fi if ! validate "$DEFAULT_DNS" "dns" "Invalid DNS IP address format. Use standard IP format (e.g., 10.6.0.7)."; then exit 1 fi # Enable logging exec > >(tee -a "${LOG_FILE}") 2>&1 # Error trap and cleanup trap 'echo "An error occurred. Cleaning up..."; rm -f "${WG_CONF_DIR}/server_privatekey"; exit 1' ERR # Debugging output echo "DEBUG: SERVER_IP=${SERVER_IP}, SUBNET=${SUBNET}, SUBNET_PREFIX=${SUBNET_PREFIX}, FULL_SUBNET=${FULL_SUBNET}" # Validate IP address format validate_ip() { if ! [[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$ ]]; then echo "Error: Invalid IP address format. Use CIDR notation (e.g., 10.100.0.1/24)." exit 1 fi } validate_ip "${SERVER_IP}" # Check for route conflicts check_route_conflict() { if ip route | grep -q "${FULL_SUBNET}"; then echo "Warning: ${FULL_SUBNET} conflicts with an existing route." read -p "Do you want to continue anyway? (y/n): " CONTINUE if [[ "${CONTINUE}" != "y" ]]; then echo "Aborting due to route conflict." exit 1 fi fi } check_route_conflict # Validate Pi-hole DNS IP format (simple IP address validation) validate_dns_ip() { if ! [[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then echo "Invalid IP address format for DNS. Use a standard IP format (e.g., 10.6.0.7)." exit 1 fi } validate_dns_ip "${DEFAULT_DNS}" # Validate port availability validate_port() { if ss -tuln | grep -q ":${SERVER_PORT}"; then if wg show wg0 | grep -q "listening port: ${SERVER_PORT}"; then echo "WireGuard is already using port ${SERVER_PORT}. Restarting service." systemctl restart wg-quick@wg0 else echo "Port ${SERVER_PORT} is in use by another process. Resolve the conflict before proceeding." exit 1 fi fi } # Log rotation setup setup_log_rotation() { cat <<EOF > /etc/logrotate.d/wireguard ${LOG_FILE} { daily rotate 7 compress missingok notifempty } EOF echo "Log rotation configured." } setup_log_rotation # Display server configuration display_server_config() { echo "------------------------------------" echo "WireGuard Server Configuration:" echo "------------------------------------" echo "Server IP: ${SERVER_IP}" echo "Server Port: ${SERVER_PORT}" echo "Pi-hole DNS: ${DEFAULT_DNS}" echo "Configuration File: ${DEFAULTS["wg_conf_file"]}" echo "Device Configurations

Читать полностью…

r_bash

Is there a way to know history of update?

Edited: title should say Uptime and not update

Hi, I'd like to get something like a uptime history...

for add time to use in last 2 days for check battery use...

I think batt is dead at 2 hours.

thanks and regards!

https://redd.it/1h9jhwe
@r_bash

Читать полностью…

r_bash

Parse urls, print those not found

I have a list of urls in the forms:

https://abc.com/d341/en/ab/cd/ef/gh/cat-ifje-full
https://abc.com/defw/en/cat-don
https://abc.com/ens/cat-ifje
https://abc.com/dm29/dofne-don-partial
https://abc.com/ens/mew-feo
https://abc.com/ens/mew-feo-partial
https://def.com/fgew/dofne-don-full

The only thing that matters are abc.com urls (I don't care about URLs from other domains) and its last "field" of the url with the suffix -full and -partial being optional. When there are duplicates, prefer first the -full version, then the -partial version. In the above example, 1st and 3rd urls are duplicates and the 3rd url should be excluded from the list. 5th and 6th urls are the same and the 6th url should be excluded from the list.

Now the unique list of items are:

cat-ifje
cat-don
mew-feo
dofne-don


From this list, I apply a command likefind to search my filesystem to each item to see if I have a file containing this name of this item as a substring.

Now, how do I get back the original url if there are no results from find for the item? The output I'm looking for is:

https://abc.com/d341/en/ab/cd/ef/gh/cat-ifje-full
https://abc.com/defw/en/cat-don
https://abc.com/dm29/dofne-don-full
https://abc.com/ens/mew-feo-partial
https://abc.com/dm29/dofne-don-partial

I think working from my existing solution to "search the item not found" from the array of URLs would be in-efficient. I guess an associative array from the start can work?

I'm processing several hundreds of items, applying find to each. I've gotten up to the point where I have the list of items not found from the filesystem, so I only need to get back their original URLs.

Any solutions much appreciated. Can even be a single awk command.

https://redd.it/1h8jdoq
@r_bash

Читать полностью…

r_bash

Which is better for capturing function output

Which is the better way to capture output from a function? Passing a variable name to a function and creating a reference with declare -n, or command substitution? What do you all prefer?

What I'm doing is calling a function which then queries an API which returns a json string. Which i then later parse. I have to do this with 4 different API endpoints to gather all the information i need. I like to keep related things stored in a dictionary. I'm sure I'm being pedantic but i can't decide between the two.

mydictjson="$(somefunc)"
vs.
some
func mydict

Is there that much of a performance hit with the subshell that spawns with command substitution?

https://redd.it/1h8cuhy
@r_bash

Читать полностью…

r_bash

Unexpected evaluatoin of "date +%M" in ~/.bashrc

I use the following command in an alias in my bashrc

$(date +%Y)/$(date +%M)/KW$(date +%V)-$(( $(date +%V) +2))

Why on earth does it evaluate to something like 2024/23/KW49-51 and an ever changing month? I cannot even figure out, what is the problem. Sometimes when sourcing the bashrc I get a new month, sometimes not. What is happening here?

https://redd.it/1h81d98
@r_bash

Читать полностью…

r_bash

replacing placeholders in a file with variables from a script

Yeah, this title probably doesn't make sense so here I go...

I have a txt file with a bunch of html code that will make up a person's signature. In the txt file I have {{firstname}} {{lastname}} and {{email}}. In my bash script I have variables $firstname $lastname and $email. I want to write the txt file to a html file but replace the placeholders in the txt file with what the variables are.

https://redd.it/1h7li6n
@r_bash

Читать полностью…

r_bash

I Asked ChatGPT About ‘ShowFilesHere’—It Took Me to the Actual Project Link!
https://github.com/andrewrgarcia/files-here-wzrd

https://redd.it/1h7um27
@r_bash

Читать полностью…

r_bash

How to exclude a directory from find and rsync except for a few very specific files?

I'm struggling with nested include/exclude for find and rsync.

I want to find or rsync my dotfiles, except for the .mozilla folder (among some others). But I want the login data of firefox preserved. So far, I have

find -path '*/.*' -not -path '*/.cache/*' -not -path '*/.mozilla/*' -path '*/.mozilla/firefox/*.default-release/{autofill-profiles,signedInUser,prefs}.js*' > dotfiles

which gives back a blank file. How can I do this properly to exclude the majority of stuff from one directory, but still include these specific files?

I haven't yet tackled this for rsync (and maybe tar), but solutions for these are also welcome.

https://redd.it/1h75w8x
@r_bash

Читать полностью…

r_bash

Any way to hook into 'command not found' and run a script / function?

Curious if there's any way to hook into the error condition 'command not found' and run a script/function? Basically, I'd like to do something similar to "thefuck" but have it run automatically.

$ doesnotexist
-bash: doesnotexist: command not found

# how to (automatically) call some custom function/script/etc?
# preferably with access to bash history so I can run a
# fuzzy find with target command vs my defined aliases

So far my searches keep coming up with irrelevant stuff so I'm not sure if I'm just using bad search terms or if this is something that is just not possible under bash.

https://redd.it/1h65lkg
@r_bash

Читать полностью…

r_bash

Why this loop doesn't break the first time?

while read -r line
do
echo "$line"
done <file.txt


Here, the condition read -r line has nothing to read the first time the loop runs, why it doesn't break the first time?

https://redd.it/1h526bx
@r_bash

Читать полностью…

r_bash

Hex to ASCII conversion - noob question

Hi all, freshly joined noobie here :)

I am currently working as a jr embedded software engineer, and have been struggling with data collection at runtime of the application.
I'm using a debugger that keeps sending a variable's hex value to the host pc via usb, but since this value is interpreted as ASCII, I see invalid symbols on the terminal.

As naive as it may sound, my question is: is there a way with a script to "get in between" the debugger and the terminal on the host pc to convert these hex values in their ASCII counterpart, so they are displayable "correctly"? (like, if I send 0x0123 I'd like the terminal to show "291" instead of the symbols associated with 0x01 and 0x23).
Extra question: do you have any suggestion on material I can study on to get a solid knowledge of bash scripting in general, too?

Thank you for your time and your patience, I hope I didn't sound too stupid haha.

https://redd.it/1hchsln
@r_bash

Читать полностью…

r_bash

Cron Python Venv VPS issue

Hi guys,

0 0 * * * source $VENV_ACTIVATE && python $SCRIPT_PATH >> $LOG_FILE 2>&1


I am trying to run $SCRIPT_PATH, which requires to activate a Python’s Virtual Environment, at midnight UTC then redirect Std out and err into $LOG_FILE.

When I check systemctl status cron the cron is running like clockwork but the $LOG_FILE isn’t being overwritten.

“The cron is running like clockwork” but only the first part source $VENV_ACTIVATE is mentioned (in the status / log). If I remember correctly.

Everything works as planned when I manually run the cron’s command.

Running it on a VPS… The paths are absolute.

That’s the whole setup:


# Set timezone to UTC
log "Setting timezone to UTC..."
sudo timedatectl set-timezone UTC

# Define the cron job command
CRON_JOB="0 0 * * * source $VENV_ACTIVATE && python $SCRIPT_PATH > $LOG_FILE 2>&1"

# Add the cron job
log "Adding the cron job to execute the script at 00:00 UTC daily..."
(crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -

# Verify if the cron job was added successfully
if crontab -l | grep -q "$SCRIPT_PATH"; then
log "Cron job successfully added."
else
log "Error: Failed to add the cron job."
exit 1
fi


Got no error or whatever but I can’t really see if the program is running. It’s just that the log file isn’t being overwritten therefore I wonder if it’s running at all.

The python file is outputing prints and logs.

cron.service is enabled by systemctl.

The job is within crontab -l

I mean looks like it’s running.

https://redd.it/1hbjx9p
@r_bash

Читать полностью…

r_bash

"${WG_CONF_FILE}" | less ;; 6) backup_config cleanup_wg0 ;; 7) show_qr_code ;; 8) backup_config cleanup_client_configs ;; 9) echo "Exiting WireGuard management." break ;; *) echo "Invalid option. Please try again." ;; esac done

https://redd.it/1hacgpt
@r_bash

Читать полностью…

r_bash

not found. Aborting." return fi # Retrieve the client's AllowedIPs and PublicKey dynamically local CLIENT_ALLOWED_IP CLIENT_ALLOWED_IP=$(grep -Po '(?<=Address = )[^\s]+' "${CLIENT_CONF_FILE}") local CLIENT_PUBLIC_KEY CLIENT_PUBLIC_KEY=$(grep -Po '(?<=PublicKey = )[^\s]+' "${CLIENT_CONF_FILE}") echo "DEBUG: Removing client '${CLIENT_NAME}' with IP: ${CLIENT_ALLOWED_IP} and PublicKey: ${CLIENT_PUBLIC_KEY}" # Escape any special characters in the PublicKey for sed local ESCAPED_PUBLIC_KEY ESCAPED_PUBLIC_KEY=$(printf '%s\n' "${CLIENT_PUBLIC_KEY}" | sed -e 's/[\/&]/\\&/g') # Remove the specific peer block from wg0.conf using the PublicKey if grep -q "PublicKey = ${CLIENT_PUBLIC_KEY}" "${WG_CONF_FILE}"; then sed -i "/\[Peer\]/,/^$/ { /PublicKey = ${ESCAPED_PUBLIC_KEY}/,/^$/ d }" "${WG_CONF_FILE}" echo "Peer with PublicKey ${CLIENT_PUBLIC_KEY} removed from wg0.conf." else echo "Warning: Peer with PublicKey ${CLIENT_PUBLIC_KEY} not found in wg0.conf." fi # Remove the client's configuration file rm -f "${CLIENT_CONF_FILE}" "${CLIENT_CONF_FILE}.png" echo "Client configuration files for '${CLIENT_NAME}' removed." # Restart WireGuard to apply changes echo "Restarting WireGuard service..." restart_wireguard echo "Client '${CLIENT_NAME}' removed successfully." } # Clean up wg0.conf by removing orphaned peers cleanup_wg0() { echo "------------------------------------" echo " Clean Up WireGuard Config " echo "------------------------------------" # Backup the current WireGuard configuration backup_config # Extract all public keys from wg0.conf local WG_PUBLIC_KEYS=($(grep -A 1 "\[Peer\]" "${WG_CONF_FILE}" | grep "PublicKey" | awk '{print $3}')) # Identify all existing public keys from client configuration files local EXISTING_CLIENT_KEYS=() for CLIENT_CONF in "${DEVICE_CONFIG_DIR}"/*.conf; do if [[ -f "${CLIENT_CONF}" ]]; then CLIENT_PUBLIC_KEY=$(grep "PublicKey" "${CLIENT_CONF}" | awk '{print $3}') EXISTING_CLIENT_KEYS+=("${CLIENT_PUBLIC_KEY}") fi done # Remove only orphaned peers from wg0.conf local CLEANED=false for WG_KEY in "${WG_PUBLIC_KEYS[@]}"; do if [[ ! " ${EXISTING_CLIENT_KEYS[*]} " =~ ${WG_KEY} ]]; then # Escape special characters in PublicKey for sed ESCAPED_KEY=$(echo "${WG_KEY}" | sed -e 's/[\/&]/\\&/g') echo "Removing orphaned peer with PublicKey: ${WG_KEY}" sed -i "/\[Peer\]/,/^$/ { /PublicKey = ${ESCAPED_KEY}/,/^$/ d }" "${WG_CONF_FILE}" CLEANED=true fi done # Remove leftover empty [Peer] blocks sed -i '/^\[Peer\]$/,/^$/d' "${WG_CONF_FILE}" if [[ "${CLEANED}" == true ]]; then echo "wg0.conf cleaned up successfully." else echo "No orphaned peers found in wg0.conf." fi # Restart WireGuard service restart_wireguard } # Clean up Client Configuration files cleanup_client_configs() { echo "------------------------------------" echo " Clean Up Orphaned Client Configs " echo "------------------------------------" # Backup the current configuration local BACKUP_FILE="/etc/wireguard/backup_$(date +%Y%m%d_%H%M%S).conf" cp "${WG_CONF_FILE}" "${BACKUP_FILE}" echo "Backup saved in ${BACKUP_FILE}." # Collect all PublicKeys from wg0.conf local WG_PUBLIC_KEYS=($(grep -Po '(?<=PublicKey = )[^\s]+' "${WG_CONF_FILE}")) echo "DEBUG: PublicKeys in wg0.conf: ${WG_PUBLIC_KEYS[*]}" # Collect all PublicKeys from client config files local CLIENT_PUBLIC_KEYS=() for CLIENT_FILE in "${DEVICE_CONFIG_DIR}"/*.conf; do if [[ -f "${CLIENT_FILE}" ]]; then CLIENT_PUBLIC_KEYS+=($(grep -Po '(?<=PublicKey = )[^\s]+' "${CLIENT_FILE}")) fi done echo "DEBUG: PublicKeys in client configs: ${CLIENT_PUBLIC_KEYS[*]}" # Identify orphaned peers in wg0.conf echo "Checking for orphaned peers in wg0.conf..." for WG_KEY in "${WG_PUBLIC_KEYS[@]}"; do if [[ ! " ${CLIENT_PUBLIC_KEYS[*]} " =~ " ${WG_KEY} " ]]; then echo "Orphaned peer detected with PublicKey: ${WG_KEY}" sed -i -e "/\[Peer\]/,/^$/ { /PublicKey = ${WG_KEY}/d; }" "${WG_CONF_FILE}" || { echo "Failed to remove peer with PublicKey: ${WG_KEY} from wg0.conf." } echo "Removed orphaned peer with PublicKey: ${WG_KEY} from wg0.conf." fi done # Identify orphaned client configuration files echo "Checking for orphaned

Читать полностью…

r_bash

Directory: ${DEFAULTS["device_config_dir"]}" echo "Log File: ${LOG_FILE}" echo "------------------------------------" } validate_wg0_consistency() { echo "Validating WireGuard configuration consistency..." # Extract public keys from wg0.conf local WG_PUBLIC_KEYS=($(grep -A 1 "\[Peer\]" "${WG_CONF_FILE}" | grep "PublicKey" | awk '{print $3}')) # Extract public keys from client configuration files local CLIENT_PUBLIC_KEYS=() for CLIENT_CONF in "${DEVICE_CONFIG_DIR}"/*.conf; do if [[ -f "${CLIENT_CONF}" ]]; then CLIENT_PUBLIC_KEYS+=("$(grep "PublicKey" "${CLIENT_CONF}" | awk '{print $3}')") fi done # Check for mismatches local MISMATCH=false for CLIENT_KEY in "${CLIENT_PUBLIC_KEYS[@]}"; do if [[ ! " ${WG_PUBLIC_KEYS[*]} " =~ ${CLIENT_KEY} ]]; then echo "Warning: PublicKey ${CLIENT_KEY} from client config is missing in wg0.conf." MISMATCH=true fi done for WG_KEY in "${WG_PUBLIC_KEYS[@]}"; do if [[ ! " ${CLIENT_PUBLIC_KEYS[*]} " =~ ${WG_KEY} ]]; then echo "Warning: PublicKey ${WG_KEY} from wg0.conf is missing in client configs." MISMATCH=true fi done if [[ "${MISMATCH}" == true ]]; then echo "Inconsistencies detected. Do you want to clean up orphaned peers? (y/n)" read -r CLEANUP_CHOICE if [[ "${CLEANUP_CHOICE}" == "y" ]]; then cleanup_wg0 fi else echo "WireGuard configuration is consistent." fi } # Backup existing configuration backup_config() { BACKUP_DIR="${WG_CONF_DIR}/backup_$(date +%Y%m%d_%H%M%S)" mkdir -p "${BACKUP_DIR}" cp "${WG_CONF_FILE}" "${BACKUP_DIR}/" 2>/dev/null || true echo "Backup saved in ${BACKUP_DIR}." } # Restart WireGuard with logging restart_wireguard() { log INFO "Restarting WireGuard service..." systemctl restart wg-quick@wg0 if ! systemctl is-active --quiet wg-quick@wg0; then echo "Error: WireGuard failed to restart. Check logs for details." exit 1 fi echo "WireGuard restarted successfully." } # Generate unique client IP generate_unique_client_ip() { while true; do # Generate a random valid IP in the subnet CLIENT_IP="${SUBNET_PREFIX%.*}.$(shuf -i 2-254 -n 1)/32" # Debugging: Output generated CLIENT_IP echo "DEBUG: Trying CLIENT_IP=${CLIENT_IP}" >&2 # Ensure the IP is not already in the configuration if [[ -n "${CLIENT_IP}" && -n "${WG_CONF_FILE}" ]] && ! grep -q "${CLIENT_IP%/*}" "${WG_CONF_FILE}"; then echo "${CLIENT_IP}" return fi done } # Display QR Code display_qr_code() { local CLIENT_CONF_FILE=$1 local QR_CODE_FILE="${CLIENT_CONF_FILE}.png" if command -v fbi &>/dev/null; then echo "Displaying QR code for configuration..." fbi -a "${QR_CODE_FILE}" 2>/dev/null elif command -v img2txt &>/dev/null; then echo "Displaying QR code as ASCII art..." img2txt "${QR_CODE_FILE}" --width=40 else echo "No compatible QR code viewer found. You can view the QR code file at: ${QR_CODE_FILE}" fi } # Validate Client Name validate_client_name() { local CLIENT_NAME=$1 # Ensure the client name only contains valid characters if ! validate "$CLIENT_NAME" "client-name" "Client name can only contain letters, numbers, dashes, and underscores."; then exit 1 fi # Check if the client name already exists in the configuration if grep -qi "$CLIENT_NAME" "${WG_CONF_FILE}"; then echo "Error: Client name '$CLIENT_NAME' already exists. Choose a unique name." exit 1 fi } validate_peers() { local WG_PUBLIC_KEYS=($(grep -A 1 "\[Peer\]" "${WG_CONF_FILE}" | grep "PublicKey" | awk '{print $3}')) local CLIENT_KEYS=() for CLIENT_CONF in "${DEVICE_CONFIG_DIR}"/*.conf; do if [[ -f "${CLIENT_CONF}" ]]; then CLIENT_KEYS+=("$(grep "PublicKey" "${CLIENT_CONF}" | awk '{print $3}')") fi done echo "Validating peer entries in wg0.conf..." for WG_KEY in "${WG_PUBLIC_KEYS[@]}"; do if [[ ! " ${CLIENT_KEYS[*]} " =~ ${WG_KEY} ]]; then echo "Orphaned peer detected: ${WG_KEY}" fi done } # Add a client # Add a client add_client() { local CLIENT_NAME=$1 local TUNNEL_MODE=$2 validate_client_name "${CLIENT_NAME}" validate_tunnel_mode "${TUNNEL_MODE}" log DEBUG "Tunnel mode validated as ${TUNNEL_MODE}" # Function to ensure the PublicKey is unique ensure_unique_public_key() { local GENERATED_KEY=$1 # Check wg0.conf for the PublicKey if grep -q "PublicKey =

Читать полностью…

r_bash

Remove function issue Wireguard Server config

Hello all,

Not sure if this is the proper place for this but I am having an issue with a bash script I am trying to write on my Raspberry Pi. The purpose of the script is to be a fully automated Wireguard Server Manager. Upon defining the Home LAN subnet, WG Server IP, Wireguard port, and DNS IP. Your then shown a menu of 8 options. 1.) Add Client 2.) Remove Client 3.) List Clients 4.) Edit Configuration 5.) Display Server wg0.conf 6.) Clean up wg0 file 7.) Display QR code for client 8.) Clean up Orphaned Client Config.

I am having an issue with my option 2.) Remove Client. When I select option 2 to remove a selected client. It removes the client config file which is want I it to do. I also when selected option 2 I want it to remove the associated peer in the wg0.conf file but in the wg0.conf file it removes all of my peers. I for the life of me am struggling to figure out how to resolve this and its driving me nuts. So I am asking for help if it can be provided. I will paste my script below for reference.

#!/bin/bash # Unified logging function: Use log for all messages. # Log levels: # INFO - Informational messages # DEBUG - Debugging messages (enabled when DEBUG_MODE=true) # ERROR - Error messages (logged to stderr) set -e log() { local level="$1" local message="$2" local timestamp timestamp=$(date +"%Y-%m-%d %H:%M:%S") # Print directly to stdout/stderr case "$level" in INFO) echo -e "[${timestamp}] [INFO] $message" ;; DEBUG) if [[ "${DEBUG_MODE}" == true ]]; then echo -e "[${timestamp}] [DEBUG] $message" fi ;; ERROR) echo -e "[${timestamp}] [ERROR] $message" >&2 ;; *) echo -e "[${timestamp}] [UNKNOWN] $message" >&2 ;; esac } # Restrict file permissions for sensitive files umask 077 # Centralized Configuration and Defaults declare -A DEFAULTS=( ["dns"]="10.6.0.7" # Default DNS server (Pi-hole) ["port"]=51642 # Default WireGuard server port ["endpoint"]="testmachinevm.ddns.net" # Default endpoint address ["conf_dir"]="/etc/wireguard" # WireGuard configuration directory ["log_file"]="/var/log/wireguard_install.log" # WireGuard log file ) # Derived Paths DEFAULTS["device_config_dir"]="${DEFAULTS["conf_dir"]}/deviceconfigs" DEFAULTS["wg_conf_file"]="${DEFAULTS["conf_dir"]}/wg0.conf" # Enable Debug Mode (default is off; set DEBUG_MODE=true to enable detailed logs) DEBUG_MODE=${DEBUG_MODE:-false} # Function to log sensitive messages securely secure_log() { local MESSAGE="$1" logger -p authpriv.info "WireGuard Management: ${MESSAGE}" } # Function to conditionally log debug messages debug_log() { if [[ "${DEBUG_MODE}" == true ]]; then echo "DEBUG: $1" else secure_log "$1" fi } # Function to check for required dependencies check_dependencies() { local DEPENDENCIES=("micro" "qrencode" "fbi" "wg" "systemctl" "ss") local MISSING_DEPS=() local DEP_STATUS=() log INFO "Checking dependencies..." # Check dependencies in parallel for TOOL in "${DEPENDENCIES[@]}"; do { if ! command -v "$TOOL" &>/dev/null; then DEP_STATUS+=("$TOOL") fi } & done # Wait for all background checks to complete wait # Handle missing dependencies if [[ ${#DEP_STATUS[@]} -ne 0 ]]; then log ERROR "Missing dependencies: ${DEP_STATUS[*]}" log ERROR "Install missing dependencies and retry." exit 1 fi log INFO "All dependencies are installed." } # Call dependency check at the start of the script check_dependencies # Centralized configuration WG_CONF_DIR="${DEFAULTS["conf_dir"]}" WG_CONF_FILE="${DEFAULTS["wg_conf_file"]}" DEVICE_CONFIG_DIR="${DEFAULTS["device_config_dir"]}" DEFAULT_DNS="${DEFAULTS["dns"]}" DEFAULT_ENDPOINT="testmachinevm.ddns.net" DEFAULT_PORT=51642 # Default WireGuard port LOG_FILE="${DEFAULTS["log_file"]}" echo "DEBUG: LOG_FILE is set to '${LOG_FILE}'" #Validate Input validate() { local value="$1" local type="$2" local error_message="$3" case "$type" in ip) if ! [[ "$value" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$ ]]; then echo "Error: ${error_message:-Invalid IP address format. Use CIDR notation (e.g., 10.100.0.1/24).}" return 1 fi ;; dns) if ! [[ "$value" =~

Читать полностью…

r_bash

Environment variables in subshell

I have been trying to understand how env command works and have a question.

Is there any difference between

var=value somecommand
and
env var=value somecommand?

These both set the variable var for subshells and will not retain its value after somecommand finishes.

Can someone help me understand when and why env is useful. Thank you!

https://redd.it/1h9ha6s
@r_bash

Читать полностью…

r_bash

Append multiline at the begin

I have multiple lines from a grep command,. I put this lines in a variable. Ho can i append this lines at the begin of a file? I tried with sed but It don't work, i don't know because a multi lines.
Someone can help me please

https://redd.it/1h8fogz
@r_bash

Читать полностью…

r_bash

Exports block prev exports

I'm using zshell and my config exports are like that. But when i want to use lazygit or openvpn etc. it says '...not included path.' I add it with export or via config file but then I can't even use ls. Say's I have to add it to path It's in the path on .zshrc. Couldn't find solution pls help. Everything works fine in root terminal but it's not suitable i guess.

https://preview.redd.it/8qtx9l58495e1.png?width=817&amp;format=png&amp;auto=webp&amp;s=3a0a8e4e448a86ccb451d407ffa769b21adbff99

https://preview.redd.it/cxqmojw0495e1.png?width=1346&amp;format=png&amp;auto=webp&amp;s=5142078c29552f2707520a69cc505162c51d1983

https://redd.it/1h8576v
@r_bash

Читать полностью…

r_bash

Error Handling in Bash: 5 Essential Methods with Examples
https://jsdev.space/error-handling-bash/

https://redd.it/1h7xvee
@r_bash

Читать полностью…

r_bash

Need help passing argument with alias

Hi,

I want to make an alias with the word cheat. Ex. cheat topic

I tried making an alias but can't get it right. I presume because there is whitespace between the command and the argument.

alias cheat="curl cht.sh/$1"

How can I make this alias work so when I type cheat zip, and make curl cht.sh.zip the result?

Thanks.

https://redd.it/1h7p3vn
@r_bash

Читать полностью…

r_bash

Debug bash prompt

I have this in my .bashrc file for the terminal prompt and it works fine but when cursor moves beyond half of the terminal width then it messes with the text on screen. The cursor does not go beyond that point instead moves to the start of the line.

# Colours
foregroundcolor='\033[0;1;36m'
command
foreground='\0330m'
background_color_black='\033[30m'
background_color_cyan='\033[46m'

# Prompt components
info="${foreground_color}${background_color_black}${background_color_cyan}\A${foreground_color} ${foreground_color}${background_color_black}${background_color_cyan}\d${foreground_color}"
align_right='\033[$(($COLUMNS-20))C'
start='\033[1G'
prompt="${foreground_color}--> ${command_foreground}"

# Prompt string
PS1="${align_right}${info}${start}${prompt}"

https://i.redd.it/w5gzsfrzhu4e1.gif

[https://redd.it/1h6hvuw
@r_bash

Читать полностью…

r_bash

I made a bash script to exclude dropbox sync directories via command line

I code a lot in my dropbox folder to keep them synced across my devices (before git commits are viable) and unfortunately dropbox does not include an automatic way to exclude syncs. Took a while but with some guidance from claude 3.5 I hacked this together.

https://github.com/kavehtehrani/dropbox-exclude

https://redd.it/1h716kg
@r_bash

Читать полностью…

r_bash

Move files from all subfolders to root folder but new filename should contain the folders

Hello,


i have a lot of folders containing files and more sobfolders with files. I want to have all that files in the root folder and the filename should contain the folder name. For example the file /testdir1/testdir2/testfile,txt should be in /testdir1_-_testdir2_-_testfile.txt

The thing is, some years ago i had done this by accident (i think i tried just to remove bad characters from filename but by accident also replaces the / but i can't get it together again :-( )



https://redd.it/1h5mrsi
@r_bash

Читать полностью…

r_bash

Advent of Code 2024 - Day 1 Problem 1 Solution in Bash

Hi, I have been learning Bash the last two days as my first scripting language. I saw the advent of code started this year, and I thought why not try to solve it with Bash (since it's the only language I know so far." I managed to solve most of it by myself, had only to look for the sort command.

---

# Bash solution for day 1 problem 1

## Summary of the problem

- 2 Teams are searching for the locations where the Chief Historian might be.
- Each location has a 'location ID'.
- 2 Groups trying to make a complete list of 'location ID'.
- The two lists are not similar.
- Pair the smallest 'location ID' from the left with the smallest 'location ID' from the right
- Measure the distance (difference) between each 'location ID' pair.
- Measure the total aggregate distance between all 'location ID' pairs.

# inputs

A text file with the 2 lists is presented in the following format

18944   47230
94847 63037
93893 35622


## Steps to solution

1. Separate the numbers in the text file into two lists.
2. Order the numbers in each list from the smallest to the biggest.
3. Measure the distance between each 2 respective numbers.
4. Measure the total of distances.

## Solution

Save the numbers in a text file called input.txt"

#!/bin/bash

# Generate an array from the input
list=(`cat input.txt`)

# Save the even elements into list.left.txt and the odd elements into list.right.txt
for el in "${!list[@]}"
do
rem=$((${el} % 2))
if [[ rem -eq 0 ]]
then
echo "${list[$el]}" >> list.left.txt
else
echo "${list[$el]}" >> list.right.txt
fi
done

# Sorting the numbers
sort list.left.txt > list.left.sorted.txt
sort list.right.txt > list.right.sorted.txt

# create arrays from the two files
left=(`cat list.left.sorted.txt`)
right=(`cat list.right.sorted.txt`)

# calculate the difference and save it to a text file.
for ele in "${!left[@]}"
do
diff=$(("${left[$ele]}"-"${right[$ele]}"))
if [ $diff -ge 0 ]
then
echo "$diff" >> diffs.txt
else
diff=$(($diff * -1))
echo "$diff" >> diffs.txt
fi
done

# Import the differences as an array
di=(`cat diffs.txt`)

total=0

for elem in ${di[@]}
do
total=$(($total + $elem))
done
echo "$total"


https://redd.it/1h4t92n
@r_bash

Читать полностью…
Subscribe to a channel