Update noscript
I am trying to learn bash, and I wanted to make a noscript that would automatically update my system, preferably on startup. It looks like this. So far, I managed to make it run on startup, it makes a new file with correct name and that's basically it. It does not update anything or put any kind of output to file. Can you tell me what did I do wrong, or where can I find some info about it?
#!/bin/bash
# Script for automaticly updating arch linux and dumping all logs to log file.
sleep 10
RED='\0330;31m'
NC='\033[0m'
CURRENT_TIME=$(date +%d-%m-%Y-%H:%M-%S)
STRING_UPDATE="_update"
FILE_NAME="${CURRENT_TIME}${STRING_UPDATE}"
NAME=$(grep -E '^(VERSION|NAME)=' /etc/os-release)
if [ "$NAME" = "Garuda Linux" ; then
garuda-update --noconfirm >>"/home/konbor/noscriptlogs/update/$FILENAME.txt"
else
sudo pacman -Syu --noconfirm >>"/home/konbor/noscriptlogs/update/$FILENAME.txt"
fi
# /dev/null 2>&1 to skip output
UPDATE=$?
if $UPDATE -eq 1 ; then
echo "${RED}Udate failed log saved in ~/noscriptlogs/update/ as $FILENAME.txt${NC}"
bat ~/noscriptlogs/update/"$FILENAME.txt"
else
echo "Update complete"
bat ~/noscriptlogs/update/"$FILENAME.txt"
fi
https://redd.it/1eet0ms
@r_bash
I am trying to learn bash, and I wanted to make a noscript that would automatically update my system, preferably on startup. It looks like this. So far, I managed to make it run on startup, it makes a new file with correct name and that's basically it. It does not update anything or put any kind of output to file. Can you tell me what did I do wrong, or where can I find some info about it?
#!/bin/bash
# Script for automaticly updating arch linux and dumping all logs to log file.
sleep 10
RED='\0330;31m'
NC='\033[0m'
CURRENT_TIME=$(date +%d-%m-%Y-%H:%M-%S)
STRING_UPDATE="_update"
FILE_NAME="${CURRENT_TIME}${STRING_UPDATE}"
NAME=$(grep -E '^(VERSION|NAME)=' /etc/os-release)
if [ "$NAME" = "Garuda Linux" ; then
garuda-update --noconfirm >>"/home/konbor/noscriptlogs/update/$FILENAME.txt"
else
sudo pacman -Syu --noconfirm >>"/home/konbor/noscriptlogs/update/$FILENAME.txt"
fi
# /dev/null 2>&1 to skip output
UPDATE=$?
if $UPDATE -eq 1 ; then
echo "${RED}Udate failed log saved in ~/noscriptlogs/update/ as $FILENAME.txt${NC}"
bat ~/noscriptlogs/update/"$FILENAME.txt"
else
echo "Update complete"
bat ~/noscriptlogs/update/"$FILENAME.txt"
fi
https://redd.it/1eet0ms
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
Help!!!! I’m in school learning bash my professor won’t help!!!
Hello fellow bashers,
I have a few assignments left before my final an I’m doin horrible my professor are non-existent and on vacation 😡 during class. I have no guidance no one to help me and this is my last class before I graduate.
Can anyone tell me how: I can view a txt file from a folder
I tried catnames.txt
Echo $”$”
And it says doesn’t show any record of file and it clearly is in my c drive and my documents and download folder and I can see the names if I click on them.
Edit: how to view a .txt document in bash
Example: dog names.txt
Catnames.txt
https://redd.it/1efarl8
@r_bash
Hello fellow bashers,
I have a few assignments left before my final an I’m doin horrible my professor are non-existent and on vacation 😡 during class. I have no guidance no one to help me and this is my last class before I graduate.
Can anyone tell me how: I can view a txt file from a folder
I tried catnames.txt
Echo $”$”
And it says doesn’t show any record of file and it clearly is in my c drive and my documents and download folder and I can see the names if I click on them.
Edit: how to view a .txt document in bash
Example: dog names.txt
Catnames.txt
https://redd.it/1efarl8
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
I feel so stupid, just found out something about pushd, and not something obscure.
I just learned that pushd swap the top two directory in the stack and that pushd +n/-n rotate the stack. Frankly I felt that the directory stacks command were less useful than cd - .
I thought you could only change to a directory in the stack with popd but it removed a directory from the stack which would kind of make the whole thing a lot less useful. I frankly though dirs, pushd, popd were only useful in edge cases I wasn't knowledgeable enough to imagine.
Now I'm going to alias dirs to dirs -v, I wonder why it's not its default behaviour but I guess I might find out.
https://redd.it/1efxxgu
@r_bash
I just learned that pushd swap the top two directory in the stack and that pushd +n/-n rotate the stack. Frankly I felt that the directory stacks command were less useful than cd - .
I thought you could only change to a directory in the stack with popd but it removed a directory from the stack which would kind of make the whole thing a lot less useful. I frankly though dirs, pushd, popd were only useful in edge cases I wasn't knowledgeable enough to imagine.
Now I'm going to alias dirs to dirs -v, I wonder why it's not its default behaviour but I guess I might find out.
https://redd.it/1efxxgu
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
How to compare keys of two json documents?
As the noscript indicates I'd like to get a diff of the keys (and only the keys, not values) of two json documents. Anyone here who have an idea about how to do so?
https://redd.it/1eg5ac6
@r_bash
As the noscript indicates I'd like to get a diff of the keys (and only the keys, not values) of two json documents. Anyone here who have an idea about how to do so?
https://redd.it/1eg5ac6
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
Triple nest quotes, or open gnome-terminal window and execute command later?
I'm trying to make a Bash noscript that can open Minecraft servers. So far I have this working, which makes a screen for playit.gg and another for the server I'm running in a new gnome-terminal window:
if ! screen -list | grep -q "serversminecraftplayit" ;
then
screen -d -m -S "serversminecraftplayit"
fi
SERVER=$(basename "$1")
SCREEN="serversminecraft"$SERVER
if ! screen -list | grep -q $SCREEN ;
then
screen -d -m -S $SCREEN
fi
gnome-terminal -- /bin/bash -c "gnome-terminal --tab --noscript=playit.gg -- /bin/bash -c 'screen -r serversminecraftplayit'; gnome-terminal --tab --noscript=$SERVER -- /bin/bash -c 'screen -r $SCREEN'";;
But for this to work as a control panel, it needs to open a tab for each server that's currently running. One way to do that would be to add another gnome-terminal call to that last part for each running server, but to do that, I'd need a third layer of quotes so I can assign the whole last command to a variable and add calls for each server. Something like (pretending
COMMAND="gnome-terminal -- /bin/bash -c ^gnome-terminal --tab --noscript=playit.gg -- /bin/bash -c 'screen -r serversminecraftplayit';^"
COMMAND=$COMMAND" gnome-terminal --tab --noscript=$SERVER -- /bin/bash -c 'screen -r $SCREEN'"
#this would be a loop if I got it working to check for all running server screens
$COMMAND;;
The other, and probably more sensible, way to do this would be to figure out how to use either gnome-terminal or screen to open a new window, then open more screens in tabs of that same window and attach screens to them. Does anyone know how I might do either of these?
https://redd.it/1egamw2
@r_bash
I'm trying to make a Bash noscript that can open Minecraft servers. So far I have this working, which makes a screen for playit.gg and another for the server I'm running in a new gnome-terminal window:
if ! screen -list | grep -q "serversminecraftplayit" ;
then
screen -d -m -S "serversminecraftplayit"
fi
SERVER=$(basename "$1")
SCREEN="serversminecraft"$SERVER
if ! screen -list | grep -q $SCREEN ;
then
screen -d -m -S $SCREEN
fi
gnome-terminal -- /bin/bash -c "gnome-terminal --tab --noscript=playit.gg -- /bin/bash -c 'screen -r serversminecraftplayit'; gnome-terminal --tab --noscript=$SERVER -- /bin/bash -c 'screen -r $SCREEN'";;
But for this to work as a control panel, it needs to open a tab for each server that's currently running. One way to do that would be to add another gnome-terminal call to that last part for each running server, but to do that, I'd need a third layer of quotes so I can assign the whole last command to a variable and add calls for each server. Something like (pretending
^ is a triple-nested quote):COMMAND="gnome-terminal -- /bin/bash -c ^gnome-terminal --tab --noscript=playit.gg -- /bin/bash -c 'screen -r serversminecraftplayit';^"
COMMAND=$COMMAND" gnome-terminal --tab --noscript=$SERVER -- /bin/bash -c 'screen -r $SCREEN'"
#this would be a loop if I got it working to check for all running server screens
$COMMAND;;
The other, and probably more sensible, way to do this would be to figure out how to use either gnome-terminal or screen to open a new window, then open more screens in tabs of that same window and attach screens to them. Does anyone know how I might do either of these?
https://redd.it/1egamw2
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
How can i create a bash noscript to check that there is packet activity on either host IP A or host IP B?
I have this bash noscript but it is not working as intended since it gets stuck on the case that only one of the hosts have packet activity and wondering if there is a better way to solve the original problem? I do not really like having to manually check the /tmp/output files generated but it is fine for now. I just need a way to support `OR` for either host instead of waiting for both to have 10 packets worth of traffic.
#!/bin/bash
capturednstraffic() {
tcpdump -i any port 53 and host 208.40.283.283 -nn -c 10 > /tmp/output1.txt
tcpdump -i any port 53 and host 208.40.293.293 -nn -c 10 > /tmp/output2.txt
}
capturednstraffic & ping -c 10 www.instagram.com
wait
https://redd.it/1eh259z
@r_bash
I have this bash noscript but it is not working as intended since it gets stuck on the case that only one of the hosts have packet activity and wondering if there is a better way to solve the original problem? I do not really like having to manually check the /tmp/output files generated but it is fine for now. I just need a way to support `OR` for either host instead of waiting for both to have 10 packets worth of traffic.
#!/bin/bash
capturednstraffic() {
tcpdump -i any port 53 and host 208.40.283.283 -nn -c 10 > /tmp/output1.txt
tcpdump -i any port 53 and host 208.40.293.293 -nn -c 10 > /tmp/output2.txt
}
capturednstraffic & ping -c 10 www.instagram.com
wait
https://redd.it/1eh259z
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
User Creation Script - Is there a better way?
I've been an admin for many years but never really learned to noscript. Been working on this lately and I've written a couple of noscripts for creating/deleting users & files for when I want to do a lab.
The User creation and deletion noscripts work but throw some duplicate errors related to groups. I'm wondering if there is a better way to do this.
Error on Creation Script:
https://preview.redd.it/gxucc73qfyfd1.png?width=510&format=png&auto=webp&s=a29d0783dc735633a5c9d0897ac1a4a701f5b56d
Here is the noscript I'm using:
#!/bin/bash
### Declare Input File
InputFile="/home/user/noscript/newUsers.csv"
declare -a fname
declare -a lname
declare -a user
declare -a dept
declare -a pass
### Read Input File
while IFS=, read -r FirstName LastName UserName Department Password;
do
fname+=("$FirstName")
lname+=("$LastName")
user+=("$UserName")
dept+=("$Department")
pass+=("$Password")
done<$InputFile
### Loop throught input file and create user groups and users
for index in "${!user@}";
do
sudo groupadd "${dept$index}";
sudo useradd -g "${dept$index}" \
-d "/home/${user$index}" \
-s "/bin/bash" \
-p "$(echo "${pass$index}" | openssl passwd -1 -stdin)" "${user$index}"
done
### Finish Script
I'm guessing I probably need to sort the incoming CSV first and possibly run this as two separate loops, but I'm real green to noscripting and not sure where to start with something like that.
I get similar errors on the delete process because users are still in groups during the loop until the final user is removed from a group.
https://redd.it/1eh4dye
@r_bash
I've been an admin for many years but never really learned to noscript. Been working on this lately and I've written a couple of noscripts for creating/deleting users & files for when I want to do a lab.
The User creation and deletion noscripts work but throw some duplicate errors related to groups. I'm wondering if there is a better way to do this.
Error on Creation Script:
https://preview.redd.it/gxucc73qfyfd1.png?width=510&format=png&auto=webp&s=a29d0783dc735633a5c9d0897ac1a4a701f5b56d
Here is the noscript I'm using:
#!/bin/bash
### Declare Input File
InputFile="/home/user/noscript/newUsers.csv"
declare -a fname
declare -a lname
declare -a user
declare -a dept
declare -a pass
### Read Input File
while IFS=, read -r FirstName LastName UserName Department Password;
do
fname+=("$FirstName")
lname+=("$LastName")
user+=("$UserName")
dept+=("$Department")
pass+=("$Password")
done<$InputFile
### Loop throught input file and create user groups and users
for index in "${!user@}";
do
sudo groupadd "${dept$index}";
sudo useradd -g "${dept$index}" \
-d "/home/${user$index}" \
-s "/bin/bash" \
-p "$(echo "${pass$index}" | openssl passwd -1 -stdin)" "${user$index}"
done
### Finish Script
I'm guessing I probably need to sort the incoming CSV first and possibly run this as two separate loops, but I'm real green to noscripting and not sure where to start with something like that.
I get similar errors on the delete process because users are still in groups during the loop until the final user is removed from a group.
https://redd.it/1eh4dye
@r_bash
How to run noscripts in the background in Ubuntu?
Hello everyone,
I know that you can run your noscripts with “&” in the background, but this option does not work so well for me, are there perhaps other commands with which I can achieve a similar result?
Thanks for your help guys
https://redd.it/1ehb8dn
@r_bash
Hello everyone,
I know that you can run your noscripts with “&” in the background, but this option does not work so well for me, are there perhaps other commands with which I can achieve a similar result?
Thanks for your help guys
https://redd.it/1ehb8dn
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
Can I push a config file and a noscript to run with ssh?
I have a noscript to run on a remote box and there is a separate config file with variables in it that the noscript needs. What would be a smart way to handle this? Can I push both somehow?
https://redd.it/1ehtyty
@r_bash
I have a noscript to run on a remote box and there is a separate config file with variables in it that the noscript needs. What would be a smart way to handle this? Can I push both somehow?
https://redd.it/1ehtyty
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
QEMU-QuickBoot.sh | Zenity GUI launcher for quick deployment of QEMU Virtual Machines
QEMU-QuickBoot is a Bash noscript i made with the help of chatGPT, It's designed to simplify the deployment of Virtual Machines (VMs) using QEMU, with a user-friendly GUI interface provided by Zenity. It allows users to quickly create and boot VMs directly from their desktop, using connected physical devices or bootable image files as the source media. User-Friendly Interface, Utilizes Zenity to present a straightforward interface for selecting VM boot sources and configurations. Multiple Boot Options: Supports booting VMs from connected devices, various file formats (.vhd, .img, .iso), and ISO images with virtual drives or physical devices. Dynamic RAM Configuration: Allows users to specify the amount of RAM (in MB) allocated to the VM. BIOS and UEFI Support: Provides options for booting in BIOS or UEFI mode depending on the user's preference. Includes error handling to ensure smooth operation and user feedback throughout the VM setup process.
noscript here at GITHUB: https://github.com/GlitchLinux/QEMU-QuickBoot/tree/main
I appreciate any feedback or advice on how to improve this noscript!
Thank You!
https://redd.it/1ehv23e
@r_bash
QEMU-QuickBoot is a Bash noscript i made with the help of chatGPT, It's designed to simplify the deployment of Virtual Machines (VMs) using QEMU, with a user-friendly GUI interface provided by Zenity. It allows users to quickly create and boot VMs directly from their desktop, using connected physical devices or bootable image files as the source media. User-Friendly Interface, Utilizes Zenity to present a straightforward interface for selecting VM boot sources and configurations. Multiple Boot Options: Supports booting VMs from connected devices, various file formats (.vhd, .img, .iso), and ISO images with virtual drives or physical devices. Dynamic RAM Configuration: Allows users to specify the amount of RAM (in MB) allocated to the VM. BIOS and UEFI Support: Provides options for booting in BIOS or UEFI mode depending on the user's preference. Includes error handling to ensure smooth operation and user feedback throughout the VM setup process.
noscript here at GITHUB: https://github.com/GlitchLinux/QEMU-QuickBoot/tree/main
I appreciate any feedback or advice on how to improve this noscript!
Thank You!
https://redd.it/1ehv23e
@r_bash
GitHub
GitHub - GlitchLinux/QEMU-QuickBoot: QEMU-QuickBoot - Zenity GUI Interface for quick and easy deployment of QEMU Virtual Machines
QEMU-QuickBoot - Zenity GUI Interface for quick and easy deployment of QEMU Virtual Machines - GlitchLinux/QEMU-QuickBoot
Any "auto echo command" generator app or website?
Hello. I have been wondering if there is any "auto echo command" generating website or app. For example, I'd be able to put the color, format, symbols etc. easily using GUI sliders or dropdown menu, and it will generate the bash "echo" command to display it. If I select the text, and select red color, the whole text will become red; if I select bold, it will become bold. If I select both, it'll become both.
It will make it easier to generate the echo commands for various bash noscripts.
https://redd.it/1eibzu4
@r_bash
Hello. I have been wondering if there is any "auto echo command" generating website or app. For example, I'd be able to put the color, format, symbols etc. easily using GUI sliders or dropdown menu, and it will generate the bash "echo" command to display it. If I select the text, and select red color, the whole text will become red; if I select bold, it will become bold. If I select both, it'll become both.
It will make it easier to generate the echo commands for various bash noscripts.
https://redd.it/1eibzu4
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
Crontab to capture bash history to a file
The issue is crontab start a new session and history command will show empty.
It works fine on line command but not via crontab.
I tried also history <bash_history_file>
And I need to capture daily the history of an user to a file.
Thank you
https://redd.it/1eieobx
@r_bash
The issue is crontab start a new session and history command will show empty.
It works fine on line command but not via crontab.
I tried also history <bash_history_file>
And I need to capture daily the history of an user to a file.
Thank you
https://redd.it/1eieobx
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
Connecting Docker to MySQL with Bash
Mac user here who has very little experience with bash. I am trying to dockerize my spring boot app and am struggling. I ran this command to start the image:
docker run -p 3307:3006 --name my-mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.36
That worked fine, so I ran:
docker exec -t my-mysql /bin/bash
And then tried to log in with:
mysql -u root -p
After hitting enter it just goes to a new line and does nothing. I have to hit control c to get out otherwise I can't do anything. What is going wrong here? Isn't it supposed to prompt me to enter a password?
https://redd.it/1eifxtc
@r_bash
Mac user here who has very little experience with bash. I am trying to dockerize my spring boot app and am struggling. I ran this command to start the image:
docker run -p 3307:3006 --name my-mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.36
That worked fine, so I ran:
docker exec -t my-mysql /bin/bash
And then tried to log in with:
mysql -u root -p
After hitting enter it just goes to a new line and does nothing. I have to hit control c to get out otherwise I can't do anything. What is going wrong here? Isn't it supposed to prompt me to enter a password?
https://redd.it/1eifxtc
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community
Question about Bash Function
Hii, I had clicked on [this link](https://github.com/dylanaraps/pure-bash-bible) to get some information about using bash's own functionality instead of using external commands or binaries, depending on the context.
The thing is that I was looking at this function and I have some doubts:
remove_array_dups() {
# Usage: remove_array_dups "array"
declare -A tmp_array
for i in "$@"; do
[[ $i ]] && IFS=" " tmp_array["${i:- }"]=1
done
printf '%s\n' "${!tmp_array[@]}"
}
remove_array_dups "${array[@]}"
Inside the loop, I guess `[[ $i ]]` is used to not add empty strings as keys to the associative array, but I don't understand why then a parameter expansion is used in the array allocation, which adds a blank space in case the variable is empty or undefined
I don't know if it does this to add an element with an empty key and value 1 to the array in case `$i` is empty or unallocated, but it doesn't make much sense because `$i` will never be empty due to `[[ $i ]] && ...`, isn't it?
I also do not understand why the `IFS` value is changed to a blank space.
Please correct me if I am wrong or I am making a mistake in what I am saying. I understand that `IFS` acts when word splitting is performed after the different types of existing expansions or when `"$*"` is expanded.
But if the expansion is performed inside double quotes, word splitting does not act and therefore the previous `IFS` assignment would not apply, no?
Another thing I do not understand either, is the following, I have seen that for the `IFS` modification does not act on the shell environment, it can be used in conjunction with certain utilities such as read ( to affect only that input line ), you can make use of local or declare within a function or make use of a subshell, but being a parameter assignment, it would not see outside the context of the subshell ( I do not know if there is any attribute of the shell that modifies this behavior ).
In this case, this modification would affect `IFS` globally, no? Why would it do that in this case?
Another thing, in the short time I've been part of this community, I've noticed, reading other posts, that whenever possible, we usually choose to make use of bash's own functionalities instead of requiring external utilities (grep, awk, sed, basename...).
Do you know of any source of information, besides the github repo I posted above, that explains this?
At some point, I'd like to be able to be able to apply all these concepts whenever possible, and use bash itself instead of non builtin bash functionalities.
Thank you very much in advance for the resolution of the doubt.
https://redd.it/1ej6sg6
@r_bash
Hii, I had clicked on [this link](https://github.com/dylanaraps/pure-bash-bible) to get some information about using bash's own functionality instead of using external commands or binaries, depending on the context.
The thing is that I was looking at this function and I have some doubts:
remove_array_dups() {
# Usage: remove_array_dups "array"
declare -A tmp_array
for i in "$@"; do
[[ $i ]] && IFS=" " tmp_array["${i:- }"]=1
done
printf '%s\n' "${!tmp_array[@]}"
}
remove_array_dups "${array[@]}"
Inside the loop, I guess `[[ $i ]]` is used to not add empty strings as keys to the associative array, but I don't understand why then a parameter expansion is used in the array allocation, which adds a blank space in case the variable is empty or undefined
I don't know if it does this to add an element with an empty key and value 1 to the array in case `$i` is empty or unallocated, but it doesn't make much sense because `$i` will never be empty due to `[[ $i ]] && ...`, isn't it?
I also do not understand why the `IFS` value is changed to a blank space.
Please correct me if I am wrong or I am making a mistake in what I am saying. I understand that `IFS` acts when word splitting is performed after the different types of existing expansions or when `"$*"` is expanded.
But if the expansion is performed inside double quotes, word splitting does not act and therefore the previous `IFS` assignment would not apply, no?
Another thing I do not understand either, is the following, I have seen that for the `IFS` modification does not act on the shell environment, it can be used in conjunction with certain utilities such as read ( to affect only that input line ), you can make use of local or declare within a function or make use of a subshell, but being a parameter assignment, it would not see outside the context of the subshell ( I do not know if there is any attribute of the shell that modifies this behavior ).
In this case, this modification would affect `IFS` globally, no? Why would it do that in this case?
Another thing, in the short time I've been part of this community, I've noticed, reading other posts, that whenever possible, we usually choose to make use of bash's own functionalities instead of requiring external utilities (grep, awk, sed, basename...).
Do you know of any source of information, besides the github repo I posted above, that explains this?
At some point, I'd like to be able to be able to apply all these concepts whenever possible, and use bash itself instead of non builtin bash functionalities.
Thank you very much in advance for the resolution of the doubt.
https://redd.it/1ej6sg6
@r_bash
GitHub
GitHub - dylanaraps/pure-bash-bible: 📖 A collection of pure bash alternatives to external processes.
📖 A collection of pure bash alternatives to external processes. - dylanaraps/pure-bash-bible
Guide to Customizing Your Prompt With Starship
I've recently switched from Oh-My-Zsh and Powerlevel10k to Starship for my shell prompt. While those are excellent tools, my config eventually felt a bit bloated. Oh-My-Zsh offers a "batteries included" approach with lots of features out of the box, but Starship's minimalist and lightweight nature made it easier for me to configure and maintain. Also, it's cross-platform and cross-shell, which is a nice bonus.
I recently made a video about my WezTerm and Starship config, but I kinda brushed over the Starship part. Since some people asked for a deeper dive, I made another video focusing on that.
Hope you find it helpful and if you're also using Starship, I'd love to see your configs! :)
https://www.youtube.com/watch?v=v2S18Xf2PRo
https://preview.redd.it/ynug9m9r5hgd1.png?width=2560&format=png&auto=webp&s=f99ddfcc4933f97a59d81a2ad4efa57333f0e820
https://redd.it/1ej7mq9
@r_bash
I've recently switched from Oh-My-Zsh and Powerlevel10k to Starship for my shell prompt. While those are excellent tools, my config eventually felt a bit bloated. Oh-My-Zsh offers a "batteries included" approach with lots of features out of the box, but Starship's minimalist and lightweight nature made it easier for me to configure and maintain. Also, it's cross-platform and cross-shell, which is a nice bonus.
I recently made a video about my WezTerm and Starship config, but I kinda brushed over the Starship part. Since some people asked for a deeper dive, I made another video focusing on that.
Hope you find it helpful and if you're also using Starship, I'd love to see your configs! :)
https://www.youtube.com/watch?v=v2S18Xf2PRo
https://preview.redd.it/ynug9m9r5hgd1.png?width=2560&format=png&auto=webp&s=f99ddfcc4933f97a59d81a2ad4efa57333f0e820
https://redd.it/1ej7mq9
@r_bash
YouTube
Ultimate Starship Shell Prompt Setup From Scratch
In this video, we're diving deep into my Starship shell prompt config from scratch, as some of you requested. Learn how to transform your terminal with Starship and turn a basic prompt into a colorful, informative display. We'll explore the benefits of using…
My first actually useful bash noscript
So this isn't my first noscript, I tend to do a lot of simple tasks with noscripts, but never actually took the time to turn them into a useful project.
I've created a backup utility, that can keep my configuration folders on one of my homelab servers backed up.
the main noscript, is called from cron jobs, with the relevant section name passed in from the cron file.
#!/bin/bash
# backup-and-sync.sh
CFG_FILE=/etc/config.ini
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
NC="\033[0m"
WORK_DIR="/usr/local/bin"
LOCK_FILE="/tmp/$1.lock"
SECTION=$1
# Set the working directory
cd "$WORK_DIR" || exit
# Function to log to Docker logs
log() {
local timeStamp=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "${GREEN}${timeStamp}${NC} - $@" | tee -a /proc/1/fd/1
}
# Function to log errors to Docker logs with timestamp
log_error() {
local timeStamp=$(date "+%Y-%m-%d %H:%M:%S")
while read -r line; do
echo -e "${YELLOW}${timeStamp}${NC} - ERROR - $line" | tee -a /proc/1/fd/1
done
}
# Function to read the configuration file
read_config() {
local section=$1
eval "$(awk -F "=" -v section="$section" '
BEGIN { in_section=0; exclusions="" }
/^\[/{ in_section=0 }
$0 ~ "\\["section"\\]" { in_section=1; next }
in_section && !/^#/ && $1 {
gsub(/^ +| +$/, "", $1)
gsub(/^ +| +$/, "", $2)
if ($1 == "exclude") {
exclusions = exclusions "--exclude=" $2 " "
} else {
print $1 "=\"" $2 "\""
}
}
END { print "exclusions=\"" exclusions "\"" }
' $CFG_FILE)"
}
# Function to mount the CIFS share
mount_cifs() {
local mountPoint=$1
local server=$2
local share=$3
local user=$4
local password=$5
mkdir -p "$mountPoint" 2> >(log_error)
mount -t cifs -o username="$user",password="$password",vers=3.0 //"$server"/"$share" "$mountPoint" 2> >(log_error)
}
# Function to unmount the CIFS share
unmount_cifs() {
local mountPoint=$1
umount "$mountPoint" 2> >(log_error)
}
# Function to check if the CIFS share is mounted
is_mounted() {
local mountPoint=$1
mountpoint -q "$mountPoint"
}
# Function to handle backup and sync
handle_backup_sync() {
local section=$1
local sourceDir=$2
local mountPoint=$3
local subfolderName=$4
local exclusions=$5
local compress=$6
local keep_days=$7
local server=$8
local share=$9
if [ "$compress" -eq 1 ]; then
# Create a timestamp for the backup filename
timeStamp=$(date +%d-%m-%Y-%H.%M)
mkdir -p "${mountPoint}/${subfolderName}"
backupFile="${mountPoint}/${subfolderName}/${section}-${timeStamp}.tar.gz"
#log "tar -czvf $backupFile -C $sourceDir $exclusions . 2> >(log_error)"
log "Creating archive of ${sourceDir}"
tar -czvf "$backupFile" -C "$sourceDir" $exclusions . 2> >(log_error)
log "//${server}/${share}/${subfolderName}/${section}-${timeStamp}.tar.gz was successfuly created."
else
rsync_cmd=(rsync -av --inplace --delete $exclusions "$sourceDir/" "$mountPoint/${subfolderName}/")
#log "${rsync_cmd[@]}"
log "Creating a backup of ${sourceDir}"
"${rsync_cmd[@]}" 2> >(log_error)
log "Successful backup located in //${server}/${share}/${subfolderName}."
fi
# Delete compressed backups older than specified days
find "$mountPoint/$subfolderName" -type f -name "${section}-*.tar.gz" -mtime +${keep_days} -exec rm {} \; 2> >(log_error)
}
# Check if the noscript is run as superuser
if [[ $EUID -ne 0 ]]; then
log_error <<< "This
So this isn't my first noscript, I tend to do a lot of simple tasks with noscripts, but never actually took the time to turn them into a useful project.
I've created a backup utility, that can keep my configuration folders on one of my homelab servers backed up.
the main noscript, is called from cron jobs, with the relevant section name passed in from the cron file.
#!/bin/bash
# backup-and-sync.sh
CFG_FILE=/etc/config.ini
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
NC="\033[0m"
WORK_DIR="/usr/local/bin"
LOCK_FILE="/tmp/$1.lock"
SECTION=$1
# Set the working directory
cd "$WORK_DIR" || exit
# Function to log to Docker logs
log() {
local timeStamp=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "${GREEN}${timeStamp}${NC} - $@" | tee -a /proc/1/fd/1
}
# Function to log errors to Docker logs with timestamp
log_error() {
local timeStamp=$(date "+%Y-%m-%d %H:%M:%S")
while read -r line; do
echo -e "${YELLOW}${timeStamp}${NC} - ERROR - $line" | tee -a /proc/1/fd/1
done
}
# Function to read the configuration file
read_config() {
local section=$1
eval "$(awk -F "=" -v section="$section" '
BEGIN { in_section=0; exclusions="" }
/^\[/{ in_section=0 }
$0 ~ "\\["section"\\]" { in_section=1; next }
in_section && !/^#/ && $1 {
gsub(/^ +| +$/, "", $1)
gsub(/^ +| +$/, "", $2)
if ($1 == "exclude") {
exclusions = exclusions "--exclude=" $2 " "
} else {
print $1 "=\"" $2 "\""
}
}
END { print "exclusions=\"" exclusions "\"" }
' $CFG_FILE)"
}
# Function to mount the CIFS share
mount_cifs() {
local mountPoint=$1
local server=$2
local share=$3
local user=$4
local password=$5
mkdir -p "$mountPoint" 2> >(log_error)
mount -t cifs -o username="$user",password="$password",vers=3.0 //"$server"/"$share" "$mountPoint" 2> >(log_error)
}
# Function to unmount the CIFS share
unmount_cifs() {
local mountPoint=$1
umount "$mountPoint" 2> >(log_error)
}
# Function to check if the CIFS share is mounted
is_mounted() {
local mountPoint=$1
mountpoint -q "$mountPoint"
}
# Function to handle backup and sync
handle_backup_sync() {
local section=$1
local sourceDir=$2
local mountPoint=$3
local subfolderName=$4
local exclusions=$5
local compress=$6
local keep_days=$7
local server=$8
local share=$9
if [ "$compress" -eq 1 ]; then
# Create a timestamp for the backup filename
timeStamp=$(date +%d-%m-%Y-%H.%M)
mkdir -p "${mountPoint}/${subfolderName}"
backupFile="${mountPoint}/${subfolderName}/${section}-${timeStamp}.tar.gz"
#log "tar -czvf $backupFile -C $sourceDir $exclusions . 2> >(log_error)"
log "Creating archive of ${sourceDir}"
tar -czvf "$backupFile" -C "$sourceDir" $exclusions . 2> >(log_error)
log "//${server}/${share}/${subfolderName}/${section}-${timeStamp}.tar.gz was successfuly created."
else
rsync_cmd=(rsync -av --inplace --delete $exclusions "$sourceDir/" "$mountPoint/${subfolderName}/")
#log "${rsync_cmd[@]}"
log "Creating a backup of ${sourceDir}"
"${rsync_cmd[@]}" 2> >(log_error)
log "Successful backup located in //${server}/${share}/${subfolderName}."
fi
# Delete compressed backups older than specified days
find "$mountPoint/$subfolderName" -type f -name "${section}-*.tar.gz" -mtime +${keep_days} -exec rm {} \; 2> >(log_error)
}
# Check if the noscript is run as superuser
if [[ $EUID -ne 0 ]]; then
log_error <<< "This
noscript must be run as root"
exit 1
fi
# Main noscript functions
if [[ -n "$SECTION" ]]; then
log "Running backup for section: $SECTION"
(
flock -n 200 || {
log "Another noscript is already running. Exiting."
exit 1
}
read_config "$SECTION"
# Set default values for missing fields
: ${server:=""}
: ${share:=""}
: ${user:=""}
: ${password:=""}
: ${source:=""}
: ${compress:=0}
: ${exclusions:=""}
: ${keep:=3}
: ${subfolderName:=$SECTION} # Will implement in a future release
MOUNT_POINT="/mnt/$SECTION"
if [[ -z "$server" || -z "$share" || -z "$user" || -z "$password" || -z "$source" ]]; then
log "Skipping section $SECTION due to missing required fields."
exit 1
fi
log "Processing section: $SECTION"
mount_cifs "$MOUNT_POINT" "$server" "$share" "$user" "$password"
if is_mounted "$MOUNT_POINT"; then
log "CIFS share is mounted for section: $SECTION"
handle_backup_sync "$SECTION" "$source" "$MOUNT_POINT" "$subfolderName" "$exclusions" "$compress" "$keep" "$server" "$share"
unmount_cifs "$MOUNT_POINT"
log "Backup and sync finished for section: $SECTION"
else
log "Failed to mount CIFS share for section: $SECTION"
fi
) 200>"$LOCK_FILE"
else
log "No section specified. Exiting."
exit 1
fi
This reads in from the config.ini file.
# Sample backups configuration
[Configs]
server=192.168.1.208
share=Backups
user=backup
password=password
source=/src/configs
compress=0
schedule=30 1-23/2 * * *
subfolderName=configs
[ZIP-Configs]
server=192.168.1.208
share=Backups
user=backup
password=password
source=/src/configs
subfolderName=zips
compress=1
keep=3
exclude=homeassistant
exclude=cifs
exclude=*.sock
schedule=0 0 * * *
The noscripts run in a docker container, and uses the other noscript to set up the environment, cron jobs, and check mount points on container startup.
#!/bin/bash
# entry.sh
CFG_FILE=/etc/config.ini
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
NC="\033[0m"
error_file=$(mktemp)
WORK_DIR="/usr/local/bin"
# Function to log to Docker logs
log() {
local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "${GREEN}${TIMESTAMP}${NC} - $@"
}
# Function to log errors to Docker logs with timestamp
log_error() {
local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
while read -r line; do
echo -e "${YELLOW}${TIMESTAMP}${NC} - ERROR - $line" | tee -a /proc/1/fd/1
done
}
# Function to syncronise the timezone
set_tz() {
if [ -n "$TZ" ] && [ -f "/usr/share/zoneinfo/$TZ" ]; then
echo $TZ > /etc/timezone
ln -snf /usr/share/zoneinfo$TZ /etc/localtime
log "Setting timezone to ${TZ}"
else
log_error <<< "Invalid or unset TZ variable: $TZ"
fi
}
# Function to read the configuration file
read_config() {
local section=$1
eval "$(awk -F "=" -v section="$section" '
BEGIN { in_section=0; exclusions="" }
/^\[/{ in_section=0 }
$0 ~ "\\["section"\\]" { in_section=1; next }
in_section && !/^#/ && $1 {
gsub(/^ +| +$/, "", $1)
gsub(/^ +| +$/, "", $2)
if ($1 == "exclude") {
exclusions = exclusions "--exclude=" $2 " "
} else {
if ($1 == "schedule") {
# Escape double quotes and backslashes
gsub(/"/, "\\\"", $2)
}
exit 1
fi
# Main noscript functions
if [[ -n "$SECTION" ]]; then
log "Running backup for section: $SECTION"
(
flock -n 200 || {
log "Another noscript is already running. Exiting."
exit 1
}
read_config "$SECTION"
# Set default values for missing fields
: ${server:=""}
: ${share:=""}
: ${user:=""}
: ${password:=""}
: ${source:=""}
: ${compress:=0}
: ${exclusions:=""}
: ${keep:=3}
: ${subfolderName:=$SECTION} # Will implement in a future release
MOUNT_POINT="/mnt/$SECTION"
if [[ -z "$server" || -z "$share" || -z "$user" || -z "$password" || -z "$source" ]]; then
log "Skipping section $SECTION due to missing required fields."
exit 1
fi
log "Processing section: $SECTION"
mount_cifs "$MOUNT_POINT" "$server" "$share" "$user" "$password"
if is_mounted "$MOUNT_POINT"; then
log "CIFS share is mounted for section: $SECTION"
handle_backup_sync "$SECTION" "$source" "$MOUNT_POINT" "$subfolderName" "$exclusions" "$compress" "$keep" "$server" "$share"
unmount_cifs "$MOUNT_POINT"
log "Backup and sync finished for section: $SECTION"
else
log "Failed to mount CIFS share for section: $SECTION"
fi
) 200>"$LOCK_FILE"
else
log "No section specified. Exiting."
exit 1
fi
This reads in from the config.ini file.
# Sample backups configuration
[Configs]
server=192.168.1.208
share=Backups
user=backup
password=password
source=/src/configs
compress=0
schedule=30 1-23/2 * * *
subfolderName=configs
[ZIP-Configs]
server=192.168.1.208
share=Backups
user=backup
password=password
source=/src/configs
subfolderName=zips
compress=1
keep=3
exclude=homeassistant
exclude=cifs
exclude=*.sock
schedule=0 0 * * *
The noscripts run in a docker container, and uses the other noscript to set up the environment, cron jobs, and check mount points on container startup.
#!/bin/bash
# entry.sh
CFG_FILE=/etc/config.ini
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
NC="\033[0m"
error_file=$(mktemp)
WORK_DIR="/usr/local/bin"
# Function to log to Docker logs
log() {
local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "${GREEN}${TIMESTAMP}${NC} - $@"
}
# Function to log errors to Docker logs with timestamp
log_error() {
local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
while read -r line; do
echo -e "${YELLOW}${TIMESTAMP}${NC} - ERROR - $line" | tee -a /proc/1/fd/1
done
}
# Function to syncronise the timezone
set_tz() {
if [ -n "$TZ" ] && [ -f "/usr/share/zoneinfo/$TZ" ]; then
echo $TZ > /etc/timezone
ln -snf /usr/share/zoneinfo$TZ /etc/localtime
log "Setting timezone to ${TZ}"
else
log_error <<< "Invalid or unset TZ variable: $TZ"
fi
}
# Function to read the configuration file
read_config() {
local section=$1
eval "$(awk -F "=" -v section="$section" '
BEGIN { in_section=0; exclusions="" }
/^\[/{ in_section=0 }
$0 ~ "\\["section"\\]" { in_section=1; next }
in_section && !/^#/ && $1 {
gsub(/^ +| +$/, "", $1)
gsub(/^ +| +$/, "", $2)
if ($1 == "exclude") {
exclusions = exclusions "--exclude=" $2 " "
} else {
if ($1 == "schedule") {
# Escape double quotes and backslashes
gsub(/"/, "\\\"", $2)
}
print $1 "=\"" $2 "\""
}
}
END { print "exclusions=\"" exclusions "\"" }
' $CFG_FILE)"
}
# Function to check the mountpoint
check_mount() {
local mount_point=$1
if ! mountpoint -q "$mount_point"; then
log_error <<< "CIFS share is not mounted at $mount_point"
exit 1
fi
}
mount_cifs() {
local mount_point=$1
local user=$2
local password=$3
local server=$4
local share=$5
mkdir -p "$mount_point" 2> >(log_error)
mount -t cifs -o username="$user",password="$password",vers=3.0 //"$server"/"$share" "$mount_point" 2> >(log_error)
}
# Create or clear the crontab file
sync_cron() {
crontab -l > mycron 2> "$error_file"
if [ -s "$error_file" ]; then
log_error <<< "$(cat "$error_file")"
rm "$error_file"
: > mycron
else
rm "$error_file"
fi
# Loop through each section and add the cron job
for section in $(awk -F '[][]' '/\[[^]]+\]/{print $2}' $CFG_FILE); do
read_config "$section"
if [[ -n "$schedule" ]]; then
echo "$schedule /usr/local/bin/backup.sh $section" >> mycron
fi
done
}
# Set the working directory
cd "$WORK_DIR" || exit
# Set the timezone as defined by Environmental variable
set_tz
# Install the new crontab file
sync_cron
crontab mycron 2> >(log_error)
rm mycron 2> >(log_error)
# Ensure cron log file exists
touch /var/log/cron.log 2> >(log_error)
# Start cron
log "Starting cron service..."
cron 2> >(log_error) && log "Cron started successfully"
# Check if cron is running
if ! pgrep cron > /dev/null; then
log "Cron is not running."
exit 1
else
log "Cron is running."
fi
# Check if the CIFS shares are mountable
log "Checking all shares are mountable"
for section in $(awk -F '[][]' '/\[[^]]+\]/{print $2}' $CFG_FILE); do
read_config "$section"
MOUNT_POINT="/mnt/$section"
mount_cifs "$MOUNT_POINT" "$user" "$password" "$server" "$share"
check_mount "$MOUNT_POINT"
log "$section: //$server/$share succesfully mounted at $MOUNT_POINT... Unmounting"
umount "$MOUNT_POINT" 2> >(log_error)
done
log "All shares mounted successfuly. Starting cifs-backup"
# Print a message indicating we are about to tail the log
log "Tailing the cron log to keep the container running"
tail -f /var/log/cron.log
log "cifs-backup now running"
I'm sure there might be better ways of achieving the same thing. But the satisfaction that I get from knowing that I've done it myself, can't be beaten.
Let me know what you think, or anything that I could have done better.
https://redd.it/1ejcdz4
@r_bash
}
}
END { print "exclusions=\"" exclusions "\"" }
' $CFG_FILE)"
}
# Function to check the mountpoint
check_mount() {
local mount_point=$1
if ! mountpoint -q "$mount_point"; then
log_error <<< "CIFS share is not mounted at $mount_point"
exit 1
fi
}
mount_cifs() {
local mount_point=$1
local user=$2
local password=$3
local server=$4
local share=$5
mkdir -p "$mount_point" 2> >(log_error)
mount -t cifs -o username="$user",password="$password",vers=3.0 //"$server"/"$share" "$mount_point" 2> >(log_error)
}
# Create or clear the crontab file
sync_cron() {
crontab -l > mycron 2> "$error_file"
if [ -s "$error_file" ]; then
log_error <<< "$(cat "$error_file")"
rm "$error_file"
: > mycron
else
rm "$error_file"
fi
# Loop through each section and add the cron job
for section in $(awk -F '[][]' '/\[[^]]+\]/{print $2}' $CFG_FILE); do
read_config "$section"
if [[ -n "$schedule" ]]; then
echo "$schedule /usr/local/bin/backup.sh $section" >> mycron
fi
done
}
# Set the working directory
cd "$WORK_DIR" || exit
# Set the timezone as defined by Environmental variable
set_tz
# Install the new crontab file
sync_cron
crontab mycron 2> >(log_error)
rm mycron 2> >(log_error)
# Ensure cron log file exists
touch /var/log/cron.log 2> >(log_error)
# Start cron
log "Starting cron service..."
cron 2> >(log_error) && log "Cron started successfully"
# Check if cron is running
if ! pgrep cron > /dev/null; then
log "Cron is not running."
exit 1
else
log "Cron is running."
fi
# Check if the CIFS shares are mountable
log "Checking all shares are mountable"
for section in $(awk -F '[][]' '/\[[^]]+\]/{print $2}' $CFG_FILE); do
read_config "$section"
MOUNT_POINT="/mnt/$section"
mount_cifs "$MOUNT_POINT" "$user" "$password" "$server" "$share"
check_mount "$MOUNT_POINT"
log "$section: //$server/$share succesfully mounted at $MOUNT_POINT... Unmounting"
umount "$MOUNT_POINT" 2> >(log_error)
done
log "All shares mounted successfuly. Starting cifs-backup"
# Print a message indicating we are about to tail the log
log "Tailing the cron log to keep the container running"
tail -f /var/log/cron.log
log "cifs-backup now running"
I'm sure there might be better ways of achieving the same thing. But the satisfaction that I get from knowing that I've done it myself, can't be beaten.
Let me know what you think, or anything that I could have done better.
https://redd.it/1ejcdz4
@r_bash
Reddit
From the bash community on Reddit
Explore this post and more from the bash community