Getting the Git commit id of a Gerrit Change Set

Oddly enough, Gerrit doesn’t report the Git commit id of its Change Sets.

The only way I found to get that piece of information is to use its SSH interface, using the query command.

The syntax is this:

ssh -p 29418 user@gerritHost gerrit query --current-patch-set <ChangeId>

replacing 29418 with the port you normally use to contact Gerrit via SSH.

That will display a number of properties about the Change Set, including the revision parameter which is the extended version of the Git commit id.

You can use the --format JSON option if you want to get a JSON representation of the same data, or you can get the short commit id using for example:

ssh -p 29418 user@gerritHost gerrit query --current-patch-set <ChangeId> \
cut -d':' -f2 | cut -c2-7

A simple script to delete multiple keys from redis all at once

When developing, you sometimes want to delete a bunch of redis keys all at once. The KEYS command gets half of the job done, but what’s missing is a convenient way to wire it to the DEL command.

In these cases, (again, when developing, as the KEYS command is check-all-keys-in-database-slow) I often rely on this script:

#!/bin/bash
#
# A simple script to delete a bunch of keys from redis all at once.
#
# Don't use it in production!!!1!1!one

read -p "redis port to connect to? [6379] " redis_port

if [[ "${redis_port}" == "" ]]; then
    redis_port="6379"
fi

if [[ ${redis_port} =~ ^[0-9]+$ ]]; then
    while true; do
        read -p "keys to delete (wildcard accepted, e.g. user:foo:bar:*): " pattern
        # read all keys into a white space separated array
        IFS=$'\r\n' GLOBIGNORE='*' :; matches=($(redis-cli --raw -p ${redis_port} keys "${pattern}"))

        # list all matches
        echo "Matching keys:"
        matching_keys=0
        for line in ${matches[@]}; do
            echo $line
            matching_keys=$((matching_keys+1))
        done

        if [[ "${matching_keys}" -eq 0 ]]; then
            echo "No keys match your query, nothing to do."
        else
            read -p "Keys that will be deleted: ${matching_keys}. Really delete? [y/N] " confirm
            case ${confirm} in
                [yY]*)
                    echo -n "Keys deleted: "
                    redis-cli --raw -p ${redis_port} del "${matches[@]}"
                    ;;
            esac
        fi
    done
else
    echo 'must specify a valid port number'
    exit 1
fi

The nice thing about it is that it shows you what keys will be deleted before deleting them, so you have a chance of not screwing up your own DB! 🙂

Use it at will, but please, don’t use it in production!

Usage is straightforward, just chmod +x the script, and call it. Use Ctrl-C to exit the script.

sudo asks for password even if NOPASSWD is set in /etc/sudoers

TL;DR when a script is not marked as executable and you try to run it with sudo, you don’t get the usual -bash: myScript.sh: Permission denied message, you are prompted for a password instead!

This one was very frustrating.

What I wanted to do was to make a user (let’s call him bran) able to execute a specific script (let’s call it /home/hodor/calm_down.sh) without having to provide his password, because the script will be executed by an automated tool (Jenkins).

I reached back to my earlier post about sudo, and updated the /etc/sudoers file so that its User privilege specification section looked like this:

root    ALL=(ALL) ALL
bran    ALL=(hodor)  NOPASSWD:  /home/hodor/calm_down.sh *

The last line gives user bran the ability to run /home/hodor/calm_down.sh as user hodor passing it any number of parameters (*) without having to provide his password (NOPASSWD:).

Saved it, su‘ed into bran, ran

bran@laketower:~$ sudo -u hodor /home/hodor/calm_down.sh "it's ok"

aaaaand…

[sudo] password for hodor: 

d’oh.

I checked the syntax in /etc/sudoers, and it was ok.

I checked whether any of the declarations that followed in /etc/sudoers could override the line I set for bran and hodor, none to be found.

Heck, I even put that line as the last line, so no line could override it. Nothing.

After a good hour of googling around and finding nothing, I remembered that the script is in a Git repository for which I just checked out a different branch. As it turned out, the script lost its executable bit.

So I set the executable bit again, as user hodor:

hodor@laketower:~$ chmod +x calm_down.sh
hodor@laketower:~$ logout
root@laketower:~# su - bran
bran@laketower:~$ sudo -u hodor /home/hodor/calm_down.sh "it's ok"
hodor.
bran@laketower:~$

it worked!

I’m sure there’s a legitimate security concern for this behavior, but dang! was this hard to figure out!