r_bash – Telegram
Out of curiosity, how many of you use shellcheck regularly? How deeply and how does it fit into your own workflows?

TL;DR - I'm just curious if/how many others actually use shellcheck, to what extent, how you add it to your own workflows, etc. Feel free to share your own experiences, stories, tips and tricks, cool ideas, alternatives, etc related to shellcheck or linting and debugging bash noscripts.

First, for those of you who have no idea what I'm talking about: see here

I've recently been updating some of my older bash noscripts to address all the issues pointed out by shellcheck (even most of the style warnings). But I've noticed several noscripts that I had yoinked from elsewhere off the web also had quite a few issues. Now, I'm not trying to shame anyone (something about people who live in glass houses not throwing rocks comes to mind lol) but it did get me to wondering how many people actually use the tool. I now have my repos setup to use the pre-commit project (the python based one - great overview here) and have been considering adding a shellcheck hook.

For those who also use it, do you just do a quick and dirty error scan? Do you fix all or most nags possible? Do you run it manually? Via git hooks? Something else?

Just curious how others use it mostly and wanted to discuss with people who will probably know wtf I'm talking about 😁

https://redd.it/1f38s1q
@r_bash
What command do you use for manage for conversion from jpg to pdf

hi, I like to know if there is a tool for get a pdf sheet form a .jpg file.

I use LO for get a pdf file, using a jpg with the size of 1 standard A4 page from LO (Libre Office).

I had qpdf tool but in its man it says that it is a tool for manage pdf.

I have txttopdf too ¿txt to pdf? I don't remember but it is for text.

Regards!

https://redd.it/1f3ejug
@r_bash
renaming multiple files using part of its original name?

I am banging my head on this, but I have a feeling I may be over thinking it.

I have a bunch of files that look like this below,

I want to rename them to the original so its just using what's previous to the underscore _

ex:

drwxrwxrwx 2 root root 4096 Aug 29 14:47 ./
drwxrwxrwx 4 root root 4096 Aug 29 13:39 ../
10.102.30.310.10.30.320110531
10.101.30.310.10.30.320110531

so after the the noscript hoping for

drwxrwxrwx 2 root root 4096 Aug 29 14:47 ./
drwxrwxrwx 4 root root 4096 Aug 29 13:39 ../
10.102.30.3
10.101.30.3

stripping out the other stuff. any easy way to do this?

https://redd.it/1f4ahmz
@r_bash
built-in printf giving crazy results

In a shell noscript I’m using bc to calculate a floating point value, assigning it to a variable then using the built-in printf function in bash – version 5.2.32(1)-release from Debian testing – and getting crazy results. Here’s a simplified example:

N1=37; N2=29; D=$(echo "scale=2; $N1 / $N2" | bc); printf "%2.2f\n" $D
0.00

Sometimes instead of 0.00 i get a number with so many digits it scrolls past what my terminal can display on one page.

If instead use the external printf command, I get the expected results:

N1=37; N2=29; D=$(echo "scale=2; $N1 / $N2" | bc); /usr/bin/printf "%2.2f\n" $D
1.27

Any ideas what’s going on? Maybe a bug in this version of bash?

https://redd.it/1f4e1io
@r_bash
Tired of waiting for shutdown before new power-on, I created a wake-up noscript.

function riseAndShine()
{
local -r hostname=${1}
while ! canPing "${hostname}" > /dev/null; do
wakeonlan "${hostname}" > /dev/null
echo "Wakey wakey ${hostname}"
sleep 5;
done
echo "${hostname} rubs eyes"
}

This of course requires relevant entries in both:

/etc/hosts:

10.40.40.40 remoteHost

/etc/ethers

de:ad:be:ef:ca:fe remoteHost

Used with:

> ssh remoteHost sudo poweroff; sleep 1; riseAndShine remoteHost

Why not just reboot like a normal human you ask? Because I'm testing systemd noscript with Conflicts=reboot.target.


----

Edit: Just realized I included a function from further up in the noscript

So for completion sake:

function canPing()
{
ping -c 1 -w 1 ${1};
local -r canPingResult=${?};
return ${canPingResult}
}

Overkill? Certainly.

https://redd.it/1f4i02s
@r_bash
While loop reading inotifywait--run the loop at least once

I have the following noscript to continually detects changes to a file then does something. Works well, but it only does something after the first change to a file and I'm trying to make it so that it does something first (i.e. runs the loop one time then detects changes before re-running the loop):

# Kill noscript on C-c but restarts the inner loop on file closeexec. `set
# -m` (monitor mode) puts the async command in its own pgid so -pid can be used
# to kill all of it, but it also ignores sigint, so added a trap back for it
# once pid is set. on't need to set trap in the loop, so can do it
# outside and check if pid is set
set -m

init=1
while IFS='' read -rd '' file; do
if [[ "$pid" ]]; then
kill -- -"$pid" &>/dev/null && printf "\n%s" "*** Paused - no valid uncomment URLs"
wait "$pid"
fi

# does something
while read -r line; do

url="${line%% *}"

yt-dlp --output "$template" -P "$dir" -- "$url" || break
# Filter out comments and empty lines
done < <(awk 'NF && !index($0, "#") == 1' < "$file") &

pid=$!
trap 'kill -- -"$pid"' INT
done < <(
if [[ "$init" == 1 ]]; then
echo "$list"
init=0
else
# Watching the directory of the file instead of the file itself handles
# whatever strategies (settings) vim uses to save file and is a more
# editor-agnostic approach. Filters only for events for this file See:
#
https://vi.stackexchange.com/a/25040
inotifywait -qme close
write --format %w%f%0 --no-newline "$(dirname "$list")" --include ".$list."
fi
)

For example, I added an init state. inotifywait returns filename for outer while loop to process, I echo the same filename but the noscript exists. How can I ensure the inner while loop runs once? Currently, the outer loop doesn't even run once. I guess it has to do with echo exiting immediately while inotifywait waits?

Any ideas much appreciated.

https://redd.it/1f4ob4l
@r_bash
Is there a better way to do this with rsync ?

I have a job and this is the logic I want to execute :

if /tmp/flagfile exists : place it in distant folder with rsync

if /tmp/flagfile and flagfile doesn't exist in distant folder : do nothing

if /tmp/flagfile doesn't exist but exists in distant folder : delete it in distant folder

I am not able to use ssh to rm remotely (only rsync available)

I have come up with this command which work, but I find overly complicated :

sudo rsync --archive --verbose --include="flagfile" --exclude="
" --delete /tmp/ /root/testdir/

For example, if I tried with this command, it would fail (file /tmp/flagfile not found)

sudo rsync --archive --verbose --delete /tmp/flagfile /root/testdir/

What do you think ?

https://redd.it/1f4qir8
@r_bash
Can you help me understand which.debianutils

I'm having a problem where `which` doesn't find java that is first in my PATH. That led to me looking at `/usr/bin/which.debianutils` on ubuntu 24.04. I don't understand what is going on here:

case $PATH in
(*[!:]:) PATH="$PATH:" ;;
esac

And this:

for PROGRAM in "$@"; do
RET=1
IFS_SAVE="$IFS"
IFS=:
case $PROGRAM in
*/*)
if [ -f "$PROGRAM" ] && [ -x "$PROGRAM" ]; then
puts "$PROGRAM"
RET=0
fi
;;
*)
for ELEMENT in $PATH; do
if [ -z "$ELEMENT" ]; then
ELEMENT=.
fi
if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then
puts "$ELEMENT/$PROGRAM"
RET=0
[ "$ALLMATCHES" -eq 1 ] || break
fi
done
;;
esac
IFS="$IFS_SAVE"
if [ "$RET" -ne 0 ]; then
ALLRET=1
fi
done

`PROGRAM` is "java" and the noscript starts with:

set -ef

What does `*` mean with globbing turned off? What is the for loop doing?

`puts` is:

printf '%s\n' "$*"

https://redd.it/1f4siaf
@r_bash
One doubt about POSIX-Compliant features

Often I have several questions about if one binary, shell builtin or any of their options are POSIX compliant or not, such as unset -v

I'd like to know is there is any resource where I can check if above stuff is POSIX compliant or not

The truth is it seems as easy as google unset -v is posix compliant or not

But I could not find anything about that.

Probably there's an IEE resource right there or something like that.

Thanks in advance!!



https://redd.it/1f50od4
@r_bash
using qpdfview: recently I get this message before showme the pdf file

Hi, recently I get the message saying me Icon Theme "abc...." not found before qpdfview showme the pdf

screenshot: https://imgbox.com/ReZm0aBp

I don't know why and the pdf is simply, or text or and img into the pdf

I don't use templates, models of pages. I just use LO for create pdf files.

recently I am starting to use convert for get pdf files.

How can delete these messages?

https://redd.it/1f5b6ur
@r_bash
Fundamentals of handling passwords securely in a shell

I'm making this for a friend though it'd be nice to have a guide to hand people in general.

My gratitude in advance for ferocious criticism. Even if it's just a link or a nitpick it'll be gratefully appreciated so I can improve.

Cheers to everyone,

---

# Fundamentals of Handling Passwords Securely in a Shell
---

While this guide is orientated toward BASH it's relevant to all POSIX shells.

It's scope is the fundamentals of password delivery between programs in a shell enviroment intended to compliment various methods of encryption, file permissioning and software options.

# Parameters
---

Parameters of commands that are executed as a new process are exposed to ALL users through `/proc/$$/cmdline` for as long as that process exists.
See permissions: `ls -la "/proc/$$/cmdline"`

Examples:

#!/usr/bin/env bash

# printf WONT leak as it's a BASH builtin and won't generate a new process.
printf '%s\n' 'my secret'


# Functions WONT leak as they're a feature of the shell.
my_func(){ :; }
my_func 'my secret'


# sshpass WILL leak 'my secret' as it's not a built-in and executes as a
# new process.
sshpass -p 'my secret'


# Some examples of commands resulting in the same leak as expansion occurs
# before execution.
sshpass -p "$(read -sr -p 'enter password: ' pass; printf '%s' "$pass")"

sshpass -p "$(cat /my/secure/file)"

sshpass -p "$(</my/secure/file)"

# Variables
---

Variables used in the CREATION of a process are exposed to the CURRENT user through `/proc/$$/environ` for as long as that process exists, mindful that there's other ways for processes running under the same user to spy on each other.
See permissions: `ls -la "/proc/$$/environ"`

Examples:

#!/usr/bin/env bash

# Variable declaration WONT leak as it's defined within the BASH process.
pass='my secret'


# A function WONT leak a variable exported into it as it's a feature of
# the shell.
my_func(){ :; }
pass='my secret' my_func


# similarly exporting a variable into a built-in won't leak as it
# doesn't run as a new process.
pass='my secret' read -t 1


# sshpass WILL leak the exported variable to `environ` because it's not a
# built-in so the variable is used in the creation of it's process.
pass='my secret' sshpass

# Interactive History
---

This only applies to using BASH's interactive CLI, not the execution of BASH noscripts.

By default commands are saved to ~/.bash_history when the terminal is closed and this file is usually readable by all users. It's recommended to `chmod 600` this file if the `$HOME` directory isn't already secured with similar permissions (ex: 700).

If a command contains sensitive information, ex: `printf '%s' 'my_api_key' | my_prog` the following are a few ways to prevent it being written to .bash_history:

1. You can use `history -c` to clear prior history
2. You can add ignorespace to HISTCONTROL so commands beginning with a space are not recorded: `[[ $HISTCONTROL == 'ignoredups' ]] && HISTCONTROL='ignoreboth' || HISTCONTROL='ignorespace'`
3. You can hard kill the terminal with `kill -9 $$` to prevent it writing history before close.


# Good Practices
---

Secrets should never be present in exported variables or parameters of commands that execute as a new process.

Short of an app secific solution, secrets should either be written to a program through an anonymous pipe (ex: `|` or `<()`) or provided in a parameter/variable as the path to a permissioned file that contains them.

Examples:

#!/usr/bin/env bash

# Only the path to the file containing the secret is leaked to `cmdline`,
# not the secret itself in the following 3 examples
my_app -f /path/to/secrets

my_app < /path/to/secrets

PASS_FILE=/path/to/secrets my_app


# Here variable `pass` stores the password entered by the uses which is
# passed as a parameter to the built-in `printf` to write it through an
# anonymous pipe to `my_app`. Then the variable is `unset` so it's not
# accidently used somewhere else in the noscript.
read -sr -p 'enter password: ' pass
printf '%s'
"$pass" | my_app
unset pass


# The noscript itself can store the key though it doesn't mix well with
# version control and seperation of concerns.
printf '%s' 'my_api_key' | my_app


# Two examples of using process substitution `<()` in place of a password
# file as it expands to the path of a private file denoscriptor.
my_app --pass-file <( read -sr -p 'enter password: ' pass; printf '%s' "$pass" )

my_app --pass-file <( printf '%s' 'my_api_key' )

# Summary
---

- Secrets should be delivered as a path to a secure file or written over an anonymous pipe.
- Secrets can be stored in local variables though it's always better to reduce attack surface and opportunity for mistakes if you have the option.
- Secrets should never be present in exported variables or parameters of commands that execute as a new process.

https://redd.it/1f5sern
@r_bash
RunBash : Seamlessly Run Bash Scripts and Linux Binaries on Windows from Explorer, Cmd, and PowerShell

Hey everyone! 👋

If you're a developer or a power user who enjoys the flexibility of Linux but often works in a Windows environment, this might be the tool you've been looking for.

# What is RunBash?

RunBash is a handy utility that allows you to run Bash noscripts and Linux binaries directly from your Windows system. It integrates seamlessly with both Windows Explorer and the Command Prompt, providing a versatile and efficient way to execute your noscripts and binaries without needing a separate terminal or extra steps.

# Key Features:

* **Direct Execution**: Run your Bash noscripts and Linux binaries directly from Windows Explorer or the Command Prompt. No need to open a separate terminal.

* **Linux Command Integration:** Easily link and manage Linux commands within your Windows environment.

* **Context Menu Integration**: Add options to the right-click context menu in Explorer, making it easy to execute noscripts or commands from any directory.

* **Customizable SourceCode:** add Any code you want to the main batchfile (\\ProgramData\\RunBash\\RunBash.bat) to adjust the execution into your needs.

* **Customizable Execution**: Control output, error handling, and execution behavior with various parameters.

* **Root/Admin Access**: Option to run noscripts with root or admin privileges, providing the flexibility to handle system-level tasks.

* **Error and Output Handling**: Fine-tune what outputs and errors are displayed or hidden, making debugging easier.

# Why Use RunBash?

RunBash bridges the gap between Windows and Linux environments, allowing you to leverage the power of Bash and Linux tools without leaving your Windows workspace. Whether you're a developer needing to run cross-platform noscripts or a power user looking to streamline your workflow, RunBash offers a robust solution, and get you out the headacke of changing every path in the arguments from windows based to Linux based.

# Getting Started

To get started with RunBash, you can check out the repository on GitHub: [benzaria/runbash](https://github.com/benzaria/RunBash).

1. **Clone the Repo**: `git clone https://github.com/benzaria/RunBash.git`
2. **Run the Setup**: Execute `setup.bat` to install and configure RunBash.
3. **Start Using It**: You can now run Bash noscripts or Linux binaries directly from Explorer or the Command Prompt!

# Feedback and Contributions

I'm always looking for feedback and ways to improve RunBash. Feel free to open issues or submit pull requests on the GitHub repo. Let's make running Linux tools on Windows as smooth as possible!

Thanks for checking it out! I hope you find RunBash as useful as I do. 🚀

https://redd.it/1f5up6l
@r_bash
sed not working within for loop

I'm trying to do this loop

for ALLSERVER in "$HOME/Games/Servers/Minecraft/"
do

echo $( sed '53!d' "$ALLSERVER/server-properties" )

done

but `sed` is interpreting the wildcard character incorrectly, in a way that `echo` doesn't, producing the following error:

sed: can't read /home/user/Games/Servers/Minecraft/
/server-properties: No such file or directory

How can I make it properly substitute the wildcard for the directory in the current iteration?

https://redd.it/1f63mbt
@r_bash
[Seeking advice + critique] I wrote a collection of noscripts on creating and using LUKS volume on Linux natively rather than with third party software like veracrypt

Scripts Link: https://gitlab.com/cy_narrator/lukshelper

Complementary article: https://utsavpoudyal.com.np/posts/Create-Encrypted-File-Container-in-Linux/

So I wanted a way to deal with sensitive files on Linux without necessarily having to encrypt the entire disk of a flash drive. Basically, what I want is a way to create an encrypted file container on Linux, sort of what Veracrypt allows you to do but without any third party software, this ensures that the volume is available even when that third party software is unavailable.

The most concern I have is in my luksCreate.sh noscript. That noscript takes in a password from the user and feeds into cryptsetup. This is done for convinience, otherwise, the user has to enter the same password three times, first two times for when cryptsetup luksFormat was performed on the volume, last one when the noscript opens the volume to format it with a filesystem. I also had to do some calculations to calculate appropriate `count` for the given block size and volume size.

Someone mentioned that it is possible for someone to terminate the noscript early and read the $password1 and $password2, I tried and it is not the case because they are bash variables, not environment variables. But regardless, the passwords are overwritten with empty string after use.

Some defaults were assumed when creating the volume which is explained in my article in **Notes and Disclaimer** section.

I dont think the password handling concern is present in other noscripts as other noscripts just call on cryptsetup and make cryptsetup prompt for the password itself. But regardless, please let me know if anything else also can be improved.

I am still learning bash, I have hardly written bash before, those too were written couple of years ago and I have totally forgotten how they were written.

Please also let me know ideas on how to make these noscripts better.

https://redd.it/1f6ie7b
@r_bash
Escaping characters is grep

I am trying to grep some text between two values but I can't escape the characters.

viewME('jkhkjhkjhkjhudydsdvvytvd')

I use this command but it keeps giving me a ( error. I tested the regex in a tester and it works without issue yet when I try grep I get errors on Arch linux. What am I missing?

grep -E '(?<=viewME\\(\\').*(?=\\'\\))'

https://redd.it/1f6ulzc
@r_bash
Script doesn't terminate after simple background process exits

Script:

#!/usr/bin/env bash

# Control Tasmota plug via MQTT
status() {
mosquittosub -h addr -u user -P 1 -t 'stat/plugc/RESULT' -C 1 | jq -r .Timers &
}

status

mosquittopub -h addr -u user -P 1 -t cmnd/plugc/timers -m "OFF"

I run mosquitto_sub in the background so it can listen and return the result of mosquitto_pub, after which it exits. I get that result, but the noscript appears to "hang" (shell prompt doesn't give me back the cursor) even though the mosquitto_sub process ends (it no longer has a pid). I need to press Enter on the shell and it returns with success code 0.

If I run those commands on the interactive shell directly, it behaves as expected--I get back my command line cursor.

Any ideas?

https://redd.it/1f6zypv
@r_bash
Is It Possible to Make SSHD Generate a New sshd_config File?

Hi all

I have made some changes to my `/etc/ssh/sshd_config` file,
and I would like to compare them to the original untouched file.

Is it possible to ask SSHD to somehow generate a new sshd_config file?
Like what I had before changing any settings..

Thank you

https://redd.it/1f79iiz
@r_bash
Is It Possible to Ask "man" to Show Only a Specific Setting?

Hi all


If you run man man,
you see that man has several options to filter the output,
for example:

> man man options [section page ...] ...

Now assume this:

You want to run man sshd_config,
and thens see only the paragraph for the PubkeyAcceptedKeyTypes setting.

Is it possible to point the command to a specific setting/paragraph?

Thank you

https://redd.it/1f7ay1b
@r_bash
Which PubkeyAcceptedAlgorithm Should I Choose for SSHD, Now that "ssh-rsa" is Less Recommended?

Hi all

Since SSHD removed "ssh-rsa" from the Default List for PubkeyAcceptedAlgorithms,
I conclude that it's an old algorithm and SSHD is trying to push users to something newer and more secure.

So in man sshd_config,
we can see the following list of Algorithms that are now in the default list:

ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
ssh-ed25519,
ecdsa-sha2-nistp256,
ecdsa-sha2-nistp384,
ecdsa-sha2-nistp521,
sk-ssh-ed25519@openssh.com,
sk-ecdsa-sha2-nistp256@openssh.com,
rsa-sha2-512,
rsa-sha2-256

Which one should I choose?

And why some of them resemble the format of an Email Address?

Thank you

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