Terminal Takeaway πŸ₯‘

There is also dnf info in Fedora. It works similar like apt policy. So at least you can see if is installed or not.

1 Like

If you want to know who you are because you forgot:

whoami

And because it is Terminal Tuesday you should look up:

calendar

1 Like

Call me immature, but when terminal output has tasteful, non-kitschy colors, I enjoy my CLI experience like 10x better. I think any and all commands (perhaps to be made into .bashrc aliases) which colorize the output are big wins, to share around.

For example, I really like glances, instead of htop now (thanks, @Mr_McBride). Even though glances takes a lot more RAM, its use of color is much more tasteful, IMHO. I hope 2021 is a year of tasteful colorization of lots and lots of common CLI utilities in Linux.

2 Likes

+1 for glances

add nethogs to that.

2 Likes

How to use multi-dimensional associative arrays in BASH

As promised, a solution in < 10 lines. Using grep with PCRE RegEx.

Introducing BAAM - [B]ASH [A]ssociative [A]rrarys in [M]ulti-dimensions

BAAM (){ # BAAM - [B]ASH [A]ssociative [A]rrarys in [M]ulti-dimensions
	REGEX_STR='(^|[^\t])\t{1}'$2'((?=\t{2}[^\t])|:)\K.*?'
	LEVEL=1
	for PROP_NAME in "${@:3}"; do
		REGEX_STR+='\t{'$((LEVEL++))'}'$PROP_NAME'((?=\t{'$(($LEVEL+1))'}[^\t])|:)\K.*?'
	done
	REGEX_STR+='[^\t](?=$|\t{1,'$LEVEL'}[^\t])'
	echo $(echo "$1" | grep -oPe "$REGEX_STR")
}

Example of use:

#!/usr/bin/env bash

# BAAM uses BAAML, a TAB deliminated multidimensional markup

# Option 1. Inline: Pass arbitrary text containing BAAML markup into a variable
{ MY_DATA=$(</dev/stdin); } <<\EOF
	SpaceX
		headquarters
			address:Rocket Road
			city:Hawthorne
			state:California
		links
			website:https://www.spacex.com/
			flickr:https://www.flickr.com/photos/spacex/
			twitter:https://twitter.com/SpaceX
			elon_twitter:https://twitter.com/elonmusk
		name:SpaceX
		founder:Elon Musk
		founded:2002
		employees:8000
EOF

# Option 2. Load: cat BAAML markup into a variable
# MY_DATA="`cat ./my_baaml.txt`"

MY_DATA=${MY_DATA//$'\n'/} # Remove newlines so grep can search it in one go

# Define search function
BAAM (){ # BAAM - [B]ASH [A]ssociative [A]rrarys in [M]ulti-dimensions
	REGEX_STR='(^|[^\t])\t{1}'$2'((?=\t{2}[^\t])|:)\K.*?'
	LEVEL=1
	for PROP_NAME in "${@:3}"; do
		REGEX_STR+='\t{'$((LEVEL++))'}'$PROP_NAME'((?=\t{'$(($LEVEL+1))'}[^\t])|:)\K.*?'
	done
	REGEX_STR+='[^\t](?=$|\t{1,'$LEVEL'}[^\t])'
	echo $(echo "$1" | grep -oPe "$REGEX_STR")
}

# Call BAAM wtih MY_DATA and each array property to reach the desired value
echo $(BAAM "$MY_DATA" SpaceX links website)

#Output: https://www.spacex.com/


If you’d like to see the process of me creating BAAM and BAAML:

Best way to simulate multidimensional arrays "objects" in BASH? - #27 by Ulfnic

This is ground floor for the project and I intend to take it a lot further. Time allowing i’ll be adding lots of features, documentation and testing.

2 Likes

Great post seen on Element.

Deep dive into BASH pitfalls.

https://mywiki.wooledge.org/BashPitfalls

1 Like

What would you like for next Terminal Tuesday?

  • Self-hosted terminal chatroom in < 20 lines using BASH and NGINX.
  • Self-host your own GeoIP lookup without using a 3rd-party service.
  • Improvements and/or new features added to BAAM.
  • Tracking down what’s using up space the fun way and the not-so-fun way.
  • Hosting a public API that allows anyone to run arbitrary code in several languages with heavy sandboxing.
  • Giving Internet to your Android using ADB over USB.

0 voters

Votes should be ranked or multiple choice in future. :confused:

For the coin flip: When DL is published, the 1st letter of the first word used at/after the 5 minute mark will decide which one I do. A to M = chatroom, N to Z = GeoIP

I demand a recount.

1 Like

How many errors has your ECC memory encountered?

If you have ECC memory you’ll probably know because it’s not a norm for personal computers. It’s usually in servers as they need max reliability and there can be a lot of memory churn (made that term up, might be real).

Inspired by natermer’s Reddit comment below after Linus expressed his disappointment with Intel’s ongoing stance on ECC. (Learn more in TWIL episode 133)

"I 100% have found dozens of production servers that were on the verge of failing and the only warning signs were ECC memory correction errors.

It’s a big deal."

How to read errors:

# Is my memory ECC!?
sudo dmidecode -t memory | grep "Type Detail:"
# Unregistered means no

# Get a reader for EDAC (Error Detection and Correction) drivers in the Kernel
sudo dnf install edac-utils # Fedora/CentOS/RHEL
sudo apt install edac-utils # Debian/Ubuntu

# Check if EDAC drivers are loaded and which memory controllers you have
edac-util --status

# Report memory controller data, error count should show up in the output
edac-util --report

Monitoring software often reads EDAC too so it’s worth confirming if your solution is checking for ECC errors.

I think the correct term is garbage collection, but that may just be the term used on the development side.

After reading this I wanted to try using curl, but I cannot integrate it on my system (KDE Neon on kernel 5.4.0-60).

This is curl I got. How do I use it on Linux?

1 Like

Tuesday again. Some inxi magic. You can make inxi show you the weather in your location, pretty cool. Of course not so cool as all those tricks by Ulfnic. :wink:

inxi -w
Weather:   Temperature: 0.7 C (33 F) Conditions: Overcast Clouds Current Time: Di 12 Jan 2021 22:19:03 CET (Europe/Berlin) 
           Source: WeatherBit.io 

Inxi is very powerful for all sorts of information about your system.

4 Likes

curl wttr.in

https://wttr.in/:help

2 Likes

2 posts were split to a new topic: Self-hosted GeoIP Lookup

Script for terminal themeing

Highlighting a brilliant project by lemnos which lets you change your terminal’s theme on the fly from a selection of 274 themes.

Install

Option 1. I want this installed for use by my user account

# Download to user's custom executable location
mkdir -p ~/.local/bin/
curl -o ~/.local/bin/theme.sh 'https://raw.githubusercontent.com/lemnos/theme.sh/master/theme.sh'

# Confirm no shenanigans
nano ~/.local/bin/theme.sh

# Make executable to current user
chmod u+x ~/.local/bin/theme.sh

Option 2. I want this installed for use by every account

Note: I changed the installation destination from /usr/bin to /usr/local/bin to follow filesystem standards.

# Download to system's custom executable location
sudo curl -o /usr/local/bin/theme.sh 'https://raw.githubusercontent.com/lemnos/theme.sh/master/theme.sh'

# Confirm no shenanigans
nano /usr/local/bin/theme.sh

# Make executable to all users
sudo chmod +x /usr/local/bin/theme.sh

Try it out

# Output CLI instructions
theme.sh

Pick a theme interactively:

theme.sh -i # Enter interactive mode to pick a theme:
# Use: theme.sh -i2 for terminals limited to 16 colors.

# Use the arrow keys or type to search
# Enter to select a theme
# Ctrl + C to quit

Before:

After:

Add this command to your .bashrc to make a theme permanent:

nano ~/.bashrc
# Add the following replacing "tempus-autumn" w/ your desired theme:
theme.sh tempus-autumn

# Save & quit
# Open a new terminal
1 Like

Learned about vertical tabs today…

image

3 Likes

We all love ls but what if you want a tree like view, just type:

ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'

Enjoy your output.

1 Like

Nice use of the cascading sed substitutions!

1 Like

Maze Game

I created a timed maze game that reads a player defined map using arbitrary text. Has hit detection and a timed win condition.

Add an X for the player, an E for the exit, spaces are where the player can travel and anything else blocks movement.

I’ve been working with arrays so much the idea popped into my head so I put it into code. You can copy/paste in any text based map you find on the Internet (so long as traversable areas are spaces) and the script will make it work. Just add an X for the player and E for exit.

#!/usr/bin/env bash
#
# === USER DEFINED MAP ===
#
# Map key:
#   - X for the player
#   - E for exit
#   - Space for traversable
#   - Any other character blocks the player's movement

{ MAP_DATA=$(</dev/stdin); } <<\EOF

   Movement: AWSD or HJKL     
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ/E\β–ˆ 
β–ˆ       β–ˆ           β–ˆ       β–ˆ 
β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ 
β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ 
β–ˆ   β–ˆ   β–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆ   β–ˆ   β–ˆ 
β–ˆ   β–ˆ           β–ˆ       β–ˆ   β–ˆ 
β–ˆ   β–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆ 
β–ˆ   β–ˆ   β–ˆ       β–ˆ   β–ˆ       β–ˆ 
β–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 
β–ˆ           β–ˆ           β–ˆ   β–ˆ 
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆ   β–ˆ 
β–ˆ       β–ˆ       β–ˆ   β–ˆ   β–ˆ   β–ˆ 
β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆ   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   β–ˆ 
β–ˆ X β–ˆ       β–ˆ               β–ˆ 
β–ˆ ^ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 
                              
EOF

# === DEFINE FUNCTIONS ===

MOVE_PLAYER(){
	# Define where the player is attempting to move
	ATTEMPT_X=$(( $1 + $PLAYER_X ))
	ATTEMPT_Y=$(( $2 + $PLAYER_Y ))
	ATTEMPT_MAP_Y_LINE=${MAP_Y[$ATTEMPT_Y]}

	# Prevent out of bounds travel
	if [ "$ATTEMPT_X" = "-1" -o "$ATTEMPT_Y" = "-1" ]; then return 1; fi

	# Is the player moving onto a win condition?
	if [ "${ATTEMPT_MAP_Y_LINE:$ATTEMPT_X:1}" = "E" ]; then

		# Get the finish time, print victory statement and exit
		FINISH_TIME=$(( SECONDS - GAME_START ))
		printf "You escaped in %s seconds" $FINISH_TIME
		if [ $PLAYER_Y == 0 ]; then printf " using \e[0;91mrule 0\e[0m"; fi
		printf "!\n\n"
		exit 1

	fi

	# Is the player attempting to move into an empty space?
	if [ "${ATTEMPT_MAP_Y_LINE:$ATTEMPT_X:1}" = $EMPTY_BLOCK ]; then

		# Erase current player location
		PLAYER_MAP_Y_LINE=${MAP_Y[$PLAYER_Y]}
		MAP_Y[$PLAYER_Y]="${PLAYER_MAP_Y_LINE:0:$PLAYER_X}${EMPTY_BLOCK}${PLAYER_MAP_Y_LINE:$(($PLAYER_X+1))}"

		# Move player coordinates
		PLAYER_X=$ATTEMPT_X
		PLAYER_Y=$ATTEMPT_Y

		# Draw new player location on updated and/or different PLAYER_MAP_Y_LINE
		PLAYER_MAP_Y_LINE=${MAP_Y[$PLAYER_Y]}
		MAP_Y[$PLAYER_Y]="${PLAYER_MAP_Y_LINE:0:$PLAYER_X}X${PLAYER_MAP_Y_LINE:$(($PLAYER_X+1))}"

		# Print map
		PRINT_MAP

	fi
}

PRINT_MAP(){
	clear
	#printf '\e[0;92m' # Make green
	printf '%s\n' "${MAP_Y[@]}"
	#printf '\e[0;0m' # Reset color
}

USER_INPUT_LOOP(){
	# Wait for the user to press a key and define it as $KEY
	read -s -n 1 KEY

	# Move the player according to the KEY's associated movement value in KEY_TO_MOVEMENT
	MOVE_PLAYER ${KEY_TO_MOVEMENT[$KEY]}

	USER_INPUT_LOOP
}

# === STARTUP ===

# Declare human input keys with movement modifiers
declare -A KEY_TO_MOVEMENT=( [w]="0 -1" [d]="1 0" [a]="-1 0" [s]="0 1" [k]="0 -1" [l]="1 0" [h]="-1 0" [j]="0 1" )

EMPTY_BLOCK="." # Special ANSI invisible character
IFS_OLD="$IFS";
IFS=""

# Replace all spaces with the EMPTY_BLOCK to simplify sequencing and add map to MAP_Y array.
MAP_DATA=$(echo $MAP_DATA | sed "s/ /$EMPTY_BLOCK/g")
readarray -t MAP_Y <<< "$MAP_DATA"

# Get player location by counting prior new lines and prior characters on the player's MAP_Y line.
PLAYER_Y=$(( `echo ${MAP_DATA%X*} | wc -l` - 1 ))
PLAYER_X=$(( `echo ${MAP_Y[$PLAYER_Y]%X*} | wc -m` -1 ))

IFS="$IFS_OLD"
GAME_START=$SECONDS
PRINT_MAP
USER_INPUT_LOOP