bash (23)

Quick WHM/cPanel All email passwords reset

You generally don’t want to use this script. This is a last resort, when all mailbox passwords for the entire account need to be changed. For this script to work, you need root access to your WHM/cPanel server. This could ruin everything, be warned!

Here be dragons!


uapi --user=$accountname Email list_pops \
  | grep email \
  | awk '{print$2}' | awk -F\@ '{print$1}' | \
  while read m; do
    echo changing password for $m
    uapi --user=@accountname Email passwd_pop domain=$domainname email=$m password=$newpass
echo done

Here are the links to the official API docs:


Is there a better way to do this? probably

Can I randomize the password? sure, but how will you send the new passwords to your users?

Hope it helps!

Similar Posts:

Quick ElasticSearch Index Cleanup

There are many solutions using curator and other libraries. I’ll try to add links here later (if I remember)

However most of the time, all that’s needed is a quick curl call

curl -X DELETE "https://${ES-Endpoint}/${INDEX_NAME}"

Get the ES endpoint from the domain overview

List the index names using

curl "https://${ES-Endpoint}/_cat/indices"

So for a quick cleanup session for everything that matches a grep

curl "https://${ES-Endpoint}/_cat/indices" | grep 'something' | awk '{print$3}' \
while read INDEX_NAME; do
  echo "Deleting ${INDEX_NAME}"
  curl -X DELETE "https://${ES-Endpoint}/${INDEX_NAME}"

Similar Posts:

MFA from command line

MFA, 2FA, 2 step validation, etc. are everywhere these days. And it’s a good thing.

Problem with using the phone to get the authentication code is that you need to have it handy at all times (when you want to login at least) and that you have to read the code then type it in (too many steps)

One possible alternative is to use the command line oathtool

Here’s my snippet, I added the following line in my .bashrc

function mfa () { oathtool --base32 --totp "$(cat ~/.mfa/$1.mfa)" | xclip -sel clip ;}

Some preparation work:

sudo apt install oathtool xclip
mkdir ~/.mfa

If you want to use the same account with both a phone based MFA generator and the shell, set them up at the same time. Simply use the generated string for setting up the account in the Google Authenticator (as an example) and the add it to the ~/.mfa/account_name.mfa

The use of xclip automatically copies the 6 digit authentication code to the clipboard. You can go ahead and paste it.

The above setup works in Ubuntu. Didn’t try it on other systems.

Similar Posts:

List IPs from CloudTrail events

A quick command to list the IPs from AWS CloudTrail events.

aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=${ACCESS_KEY_ID} --max-items ${MAX_ITEMS} \
  | jq -r '.Events[].CloudTrailEvent' \
  | jq '.sourceIPAddress' \
  | sort | uniq

This of course can be extended to include more information, for example:

aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=${ACCESS_KEY_ID} --max-items ${MAX_ITEMS} \
  | jq -r '.Events[].CloudTrailEvent' \
  | jq '{ User: .userIdentity.userName, IP: .sourceIPAddress, Event: .eventName }'

Similar Posts:

Change profiles automatically in Tilix when connecting to SSH hosts

I use Tilix as my main terminal app on Ubuntu. I like it mainly because it’s easy to use and shows multiple sessions in tiles and tabs, so it’s easy to switch between multiple servers without too much fuss

Tilix is also pretty customizable. I just needed to have the “profile” automatically switch according to the server/machine I switch to. This can be done according to the documentation per but I wanted something configured locally, not sent to the remote system.

So I just added a function that wraps my ssh command. Here’s how it looks in my .bashrc

ssh() { 
	SSHAPP=`which ssh`;   
	echo "switching to $ARGS"; 
	printf "\033]7;file://%s/\007" "$ARGS";   

This sets up the hostname of machine you’re logging into as the title. That’s your trigger. What remains is to create a profile and assign that profile to automatically switch when the trigger (hostname:directory, user can also be added) is set.

Go to Profiles > Edit Profile > Advanced (tab) and under Match add the hostname.

That’s about it. I’m going to add a new profile with a RED background now for my production machines! too much?

Update (Jan 8, 2020)

I noticed that I have also added a Match for my localhost hostname in the Default profile, so that the profile would revert to that once I logged off a remote host.

Another thing I needed was to create a special trigger if I wanted to use a wildcard match for hostnames (ie. if I wanted to switch profile on all my AWS instances via Session Manager). And match that special hostname (aws-instance below for example). Here’s my ssh bash function now:

ssh () {
     if [[ $ARGS == i-* ]]
         echo "switching to AWS instance"
         printf "\033]7;file://%s/\007" "aws-instance"
         echo "switching to $ARGS"
         printf "\033]7;file://%s/\007" "$ARGS"

Similar Posts:

Check PHP-FPM Status from CLI

It’s good to have the status page, especially if you need to troubleshoot issues that are not showing up in the regular logs, such as high load or memory consumption.

However, looking at that page and refreshing it manually is not always useful. Sometimes you need to log that data, or have a way to pinpoint a single PID causing the load.

First make sure you have the status page accessible. Here’s a tutorial I like:

The create this script on the server. Make sure to change the connect part to your PHP-FPM pool’s correct port or socket

# Requirements: cgi-fcgi
#   on ubuntu: apt-get install libfcgi0ldbl

/usr/bin/cgi-fcgi -bind -connect

if [ -n "$1" ]; then
echo -e "$RESULT" | grep -A12 "$1"
echo -e "$RESULT"

One way I use it is run `top` and check for the suspect process PID, then run ` <PID>`

Similar Posts:

Find the owner of an AWS Access Key

This is something you will have to deal with at one time or another after managing AWS IAM users for a while. Basically, it’s straight forward with the following code:

  • Get a list of users
    • for each user get their access key IDs
    • (optional) pipe to grep for checking a specific ID

And here’s the `aws-cli` code

for user in $(aws iam list-users --output text --query 'Users[*].UserName'); do     
  aws iam list-access-keys --user $user --output text; 

# or 
for user in $(aws iam list-users --output text --query 'Users[*].UserName'); do     
  aws iam list-access-keys --user $user --output text | grep $Q_ACCESSKEY 


Similar Posts:

Change Nickname in Mattermost

A colleague asked me today for a quick way to set the nickname in Mattermost. He needed to do that to provide more information about his status than what the actual “Status” in shows, which is limited to “Online”, “Away”, “Do Not Disturn” and “Offline”

So if you want to tell people you’re away for a couple of hours, or sick, walking the dog, etc. then you need to go IRC style and put the additional information in your nickname. Not too bad actually, just inconvenient.

I checked the Mattermost API docs and wrote a small bash script to get things going

# Requirements:
#  - get the token from Mattermost > Account Settings > Security > Personal Access Tokens > Create New Token
#    make sure to save the Token itself, not the ID!
#  - install jq

user_id=$(curl -sH "Authorization: Bearer $TOKEN" \ | jq -r .id)
curl -XPUT -d '{"nickname":"'$NICKNAME'"}' \
  -sH "Authorization: Bearer $TOKEN" \
curl -XPUT -d '{"status":"'$STATUS'"}' \
  -sH "Authorization: Bearer $TOKEN" \
if [ -n "$3" ]; then
  curl -XPOST -d '{"channel_id":"'"$CHANNEL_ID"'", "message":"'"$3"'"}' \
  -sH "Authorization: Bearer $TOKEN" ""

A couple of things to watch out there:

  • You need to save the TOKEN, not the TOKEN ID. Once created and saved the actual TOKEN is no longer showing in the UI. So save that somewhere safe and use it in the script
  • The user needs to be able to create their own token. Follow the procedure per the docs here to allow them to do that. Yes, you need to do all that 🙂
  • The Channel ID can be copied from the channel drop-down menu > View info. In the bottom left, in grey you will see: `ID: xxxxxxxxxx` that’s the one you need!


For convenience, I added a few aliases in my bashrc:

alias lunch=" 'abdallah|lunch' 'dnd' 'going to lunch break'"
alias back=" 'abdallah|work' 'online' 'back!'"
alias goodmorning=" 'abdallah|work' online 'Good morning :)'"

I know it’s better to add a slash-command for that. Something like ‘/nick …’ or ‘/status …’. I’ll check out those docs later.

Similar Posts:

Stop un-tagged instances

After setting up a bastion and getting GitLab runner to autoscale on EC2 spot instances, I noticed that some instances are being started but left un-tagged and probably unused. Those seem to slip through the cracks somehow .. I’m still investigating why that’s happening.
Meanwhile, to avoid paying for those instances, I set up a cron to check for non tagged instances on EC2 and terminate them.

Here’s my bash code using aws-cli

INSTANCES=$(aws ec2 describe-instances \
  --filters "Name=key-name,Values=runner-*" \
            "Name=instance-state-name,Values=running" \
  --query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | [].[InstanceId]' \
  --output text)
if [ -n "$INSTANCES" ]; then 
  aws ec2 terminate-instances --instance-ids $INSTANCES 

This looks for running instances, with the Key Name runner-* and where the tag Name is not not_null (so null!)

It’s working so far. Will keep on looking for a more permanent solution.

Similar Posts:

How NOT to ban Googlebot

Google do not provide a list of IPs to identify their bots, so you can’t simply add that to fail2ban’s ‘ignoreip =’ line.

Instead, according to their answer per you can only verify the bot’s provenance by checking the DNS for the bot’s IP. In fact, they ask you to run 2 queries (1 reverse and 1 forward lookup) to make sure that the IP is not spoofed.

My simple 1 reverse lookup script is:

HOSTRESULT="$(host -W ${IP})" # updated thanks to comment from Martin

And add that to /etc/fail2ban/jail.local

ignorecommand = /usr/local/bin/ 

This needs more testing, and I should add the second forward lookup, for for now it seems to do the trick

if [[ "$HOSTRESULT" =~ $REGEX ]]; then exit 0; else exit 1; fi

And add that to /etc/fail2ban/jail.local

This needs more testing, and I should add the second forward lookup, for for now it seems to do the trick

Similar Posts: