Tech Chorus

Systemd Unit File Just To Create A Directory Under /run

written by Sudheer Satyanarayana on 2018-01-19

On recent versions of Fedora, CentOS and RHEL, /var/run and /var/lock are mounted as /tmpfs. Also, /var/run is a symlink to /run. Because of this, if you create a directory under /run it won't stay there after a reboot.

If you are starting to migrate your service to systemd or just want to create a directory under /run using systemd, use this simple unit file. The contents of:

Description=My Service

# We just want to create the myservice run directory

Replace my.service with an appropriate name for your service. Replace the description, User and Group values to your needs.

Start the unit:

systemctl start my.service

Enable the unit so that it starts when the system boots:

systemctl enable my.service

What is wrong in using ExecStartPre=-/bin/mkdir /var/run/myservice?

Systemd can handle directory creation and setting up its attributes for you. You just specifiy the name of the directory in the RuntimeDirectory= directory. When the unit starts, systemd creates the directory and sets its owner and group to the values you specify in User= and Group= directives. So, the counter question is, when systemd can do it for you using a simple directive, why do you want to do it yourself? Also, note that the - prefix just ignores the error when the directory already exists and another attempt is made to create it. Although the error is ignored, it still shows up in red when you check the status of the service.

What is Type=oneshot?

Type=oneshot means the process is expected to exit before systemd starts follow-up units. Along with this, we also specify RemainAfterExit=yes. We tell systemd that my.service shall be considered active even when all its processes exited. When you query the status of the service, you will see that the unit is active because of this directive.

What is ExecStart=/bin/true?

Typically, you would put the path to your service executable in ExecStart= directive. In our example, we're not doing that yet. We're simply using the sytemd unit file to create the /run/myservice directory. So, we use the placeholder command /bin/true. /bin/true simply returns 0 indicating that the command was executed successfully.


journalctl Cheatsheet

written by Sudheer Satyanarayana on 2017-10-26

Between date ranges

journalctl --since "2017-10-20" --until "2017-10-21"

Between date and time ranges

journalctl --since "2017-10-20 10:00:00" --until "2017-10-21 11:00:00"

Friendlier unit values of since and until

journalctl --since "2017-10-20 10:00:00" --until "1 hour ago"
journalctl  --since "1 hour ago"
journalctl  --since "2 hour ago"  --until "1 hour ago"

View particular unit

journalctl -u alertmanager

where alertnamaner is the systemd unit name.

Kernel messages

journalctl -k

By priority

journalctl -p crit

Continuously watch like tail -f

journalctl -fu prometheus

Catalogue and jumping to end in the pager

journalctl -xe

This is particularly useful when your last command results in an error and you want to the most recent errors. The -x flag adds useful descriptive messages to errors when they are available.

Removing log entries

Retain only 1GB of data:

journalctl --vacuum-size=1G

Retain only 1 day worth of data:

journalctl --vacuum-time=1d

Retain only 2 files:

journalctl --vacuum-files=2

Installing Latest Version Of Texlive On Fedora

written by Sudheer Satyanarayana on 2017-05-19

The version of textlive shipped with Fedora 25 was too old for my needs.

$ dnf info texlive
Last metadata expiration check: 22 days, 8:44:09 ago on Wed Apr 26 22:34:24 2017.
Available Packages
Name        : texlive
Arch        : x86_64
Epoch       : 6
Version     : 2016
Release     : 33.20160520.fc25
Size        : 33 k
Repo        : updates
Summary     : TeX formatting system
URL         :
License     : Artistic 2.0 and GPLv2 and GPLv2+ and LGPLv2+ and LPPL and MIT and Public Domain and UCD and Utopia
Description : The TeX Live software distribution offers a complete TeX system for a
            : variety of Unix, Macintosh, Windows and other platforms. It
            : encompasses programs for editing, typesetting, previewing and printing
            : of TeX documents in many different languages, and a large collection
            : of TeX macros and font libraries.
            : The distribution includes extensive general documentation about TeX,
            : as well as the documentation for the included software packages.

Specifically, I wanted the updated version of tex4ebook package. The version shipped by Fedora didn't cut it. So, I had to install newer version of textlive only for certain tasks. So, I downloaded and installed texlive on a separate user account.

adduser somenewuser
su - somenewuser

Go to and get the link to the latest tarball.

wget ''

Unpack the archive.

tar -zxvf install-tl-unx.tar.gz
Execute the installer. Your directory name may vary depending on the build number.
cd install-tl-20170413/

In the installation wizard, set the TEXDIR using the D option. I set mine to ~/texlive/2016/.

The installation takes some time. Enjoy the new version of tex4ebook using the path


This way, you can use the Fedora provided version of texlive on your regular user accounts and custom textlive on special user.


written by Sudheer Satyanarayana on 2017-05-14

VIM Plugins And Notes

The plugins I use for Vim. Recently, I have started using Atom for web development. For rest my editing needs, I use Vim.

For General Editing

For Python Development

For JavaScript

Some Cool VIM Resources


written by Sudheer S on 2016-10-02

Rakesh: Golix, what's lucky for you?

Golix: Lucky, I learned probability.

PostgreSQL Cheatsheet

written by Sudheer Satyanarayana on 2016-07-25

Install PostgreSQL Server

Fedora 30:

sudo dnf install postgresql-server

CentOS 7:

sudo yum install postgresql-server

Ubuntu 18.04:

sudo apt install postgresql

New Server Initialization

On CentOS 7/Fedora 30:

sudo postgresql-setup initdb

Upgrading From An Older Version

sudo postgresql-setup --upgrade

Administering The Database Server

Managing The postgresql Daemon

Starting PostgreSQL server

sudo systemctl start postgresql

Checking PostgreSQL Server Status:

sudo systemctl status postgresql

Enabling PostgreSQL Server Systemd Unit/Enabling PostgreSQL Server On Boot:

sudo systemctl enable postgresql

Allowing Password Based Login From localhost

Edit /var/lib/pgsql/data/pg_hba.conf as privileged user(root) and add this line:

host    all     all    md5

Allowing Password Based Login From A Particular Network

Edit /var/lib/pgsql/data/pg_hba.conf as privileged user(root) and add this line:

host    all             all             md5

In this example password based login will be allowed from the network

After making changes to the pg_hba.conf file, restart PostgreSQL server.

Restarting The PostgreSQL server:

sudo systemctl restart postgresql

Listening On A Particular IP Address:

Edit the file /var/lib/pgsql/data/postgresql.conf and add:

listen_addresses = ''

Save the file and restart PostgreSQL server. This configuration will allow PostgreSQL to listen on the IP address

Listening On All IP addresses:

Edit the file /var/lib/pgsql/data/postgresql.conf and add:

listen_addresses = '*'

Save the file and restart PostgreSQL server.

Becoming postgres :

The root user of postgresql is postgres.

sudo su - postgres

Launching The PostgreSQL Console:


From the PostgreSQL console, you can perform administrative tasks such as creating and deleting users, databases, etc.

Creating A PostgreSQL User

 CREATE USER username login PASSWORD 'password';

Creating A PostgreSQL Database

 CREATE DATABASE databasename WITH OWNER = username;

Listing Databases

Launch the PostgreSQL console:

sudo su - postgres

From the PostgreSQL console, execute \d


Listing Tables Of A Database

From the PostgreSQL console:


Replace DATABASE_NAME with the actual database name.

Backing Up A Database:


For example:

pg_dump -Uusername -h databasename > my-pg-databasename-backup.sql

Restoring A Database From A Dump File

Copy the file to the host where the dump has to be restored.

sudo su - postgres
psql databasename < /path/to/dump/file

Generating The CREATE TABLE Statement For A Particular Table

pg_dump -U username -h dbname -t tablename --schema-only

Using Sass Version Of Bootstrap With Webpack

written by Sudheer Satyanarayana on 2016-07-21

You must have gone through the webpack tutorial to understand this blog post. If you have done that, using Sass version of Bootstrap is a breeze.

In your project directory install these packages using npm.

npm install bootstrap-loader css-loader node-sass resolve-url-loader sass-loader style-loader url-loader file-loader jquery imports-loader bootstrap-sass --save-dev

Create the file webpack.config.js

'use strict';

var path = require('path');

module.exports = {
    entry: ['bootstrap-loader', './index.js'],
    output: {
        path: 'output',
        filename: 'bundle.bootstrap-sass.js'
    devtool: 'inline-source-map',
    module: {
        loaders: [
                test: /bootstrap-sass\/assets\/javascripts\//, 
                loader: 'imports?jQuery=jquery'
                test: /\.woff2?$|\.ttf$|\.eot$|\.svg$/,
                loader: 'url'
                test: /\.scss$/,
                loader: 'style-loader!css-loader!'
        resolve: {
            extensions: ['', '.js', '.jsx', '.css', '.scss'],
            modulesDirectories: [

index.js: your project entry file.

/* Put whatever you want in your entry JS file */

index.html: Minimalist HTML file to check whether Bootstrap styles are loaded.

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Minimalistic webpage</title>

    <script src="output/bundle.bootstrap-sass.js"></script>

  <body role="document">
     <button type="button" class="btn btn-primary" aria-label="Left Align"><span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>Some text</button>

Generate the build


Open index.html in your browser and you should see the web page with Bootstrap styles loaded.

Firewalld Cheatsheet

written by Sudheer Satyanarayana on 2016-07-12

List supported zones

firewall-cmd --get-zones

List active zones

firewall-cmd --get-active-zones

List zones with enabled features

firewall-cmd --list-all-zones

Permanently add source IP address to a zone

firewall-cmd --permanent --zone=<zone_name> --add-source=<ip_address>

Permanently remove source IP address from a zone

firewall-cmd --permanent --zone=<zone_name> --remove-source=<ip_address>

Reload firewall

firewall-cmd --reload

Permanently add a service to zone

firewall-cmd --permanent --zone=<zone_name> --add-service=<service_name>

Permanently add an interface to a zone

firewall-cmd --permanent --zone=<zone_name> --add-interface=<interface_name>

Permanently remove an interface from a zone

firewall-cmd --permanent --zone=<zone_name> --remove-interface=<interface_name>

Adding Custom Service

Copy from a template.

cp /usr/lib/firewalld/services/https.xml /etc/firewalld/services/myservice.xml

and edit the values. If you have an interface alias, this method might suit your needs:


How To Interchange Values And Keys Of A Dictionary In Python?

written by Sudheer Satyanarayana on 2015-12-09

Here's our sample dictionary:

my_dict = {'game': 'cricket', 'planet': 'earth'} The values() method of the dictionary returns a list of values.

>>> my_dict.values()
['earth', 'cricket']

The keys() method of the dictionary returns a list of keys.

>>> my_dict.keys()
['planet', 'game']

Notice the 1-1 correspondence between the items of the returned lists. This correspondence remains unchanged if the dictionary is unchanged.

To interchange the keys and values all you have to do is zip and generate another dictionary. Let's complete the remaining steps.

zip(my_dict.values(), my_dict.keys())
[('earth', 'planet'), ('cricket', 'game')]

Now, we have a list of tuples. Each tuple contains the value and key pairs. The last step is to create a dictionary using this list. Pass the above list to the built-in function dict().

>>> dict(zip(my_dict.values(), my_dict.keys()))
{'earth': 'planet', 'cricket': 'game'}

Here's a one-liner to summarize the concept.

dict(zip(my_dict.values(), my_dict.keys()))

Github For Mercurial User

written by Sudheer Satyanarayana on 2015-03-27

You are a Mercurial user and have little experience with Github. You are required to publish your Mercurial repository on Github. The good news is, you can do it without parting with Mercurial. There are bridges between Git and Mercurial. The one we are going to talk about today, is hg-git.

Let's start demonstrating our solution.

Step 1: Create a mercurial repository somewhere

I do it on Bitbucket. We'll call this our canonical repository. Clone the repository.

hg clone ssh://

Step 2:Add some contents to the cloned repository

cd mycoolrepo/
echo "Sudheer Satyanarayana" >> contributors.txt
hg add contributors.txt
hg commit -m "Initial commit with contributors"

Step 3: Push the changes to the canonical Mercurial repository

hg push ssh://

Step 4: Create the repository on Github

There are several ways to setup the mirror. One way to do it is importing the Mercurial repository to Gitbut. But in this article, we'll directly pull and push to Github repository. While creating the Git repository on Github, I chose the option - "Initialize this repository with a README".

Step 5: Enable the hg-git extension

Edit .hg/hgrc file in your repository and add these:

hggit =

Step 6: Pull from the newly created Git repository

hg pull git+ssh://

Pulling for the first time from the newly created Git repository will create another head in your Mercurial repository. For example, running 'hg heads' shows:

changeset:   1:5b467a77b006
bookmark:    master
tag:         tip
parent:      -1:000000000000
user:        Sudheer Satyanarayana <>
date:        Fri Mar 27 22:14:32 2015 +0530
summary:     Initial commit

changeset:   0:688bd09fe790
user:        sudheer
date:        Fri Mar 27 22:07:26 2015 +0530
summary:     Initial commit with contributors
The changeset 1:5b467a77b006 is bookmarked as 'master'.

Step 7: Merge the heads

hg merge master
hg commit -m "merging master"

Step 8: Push the changeset to the canonical Mercurial repository

hg push

Move the bookmark 'master' to default and push to Githib.

hg bookmark -r default master
hg push git+ssh://

Now, you can adopt this method to work on the repository and keep pushing to both the repositories - The canonical Mercurial repository and the Github Git repository.

Work on the repository. Make some commits. Push to the canonical repository Move the bookmark 'master' to default and push to Githib Git repository If you do not move the bookmark, pushing to the Git repository makes no sense because hg-git will attempt to push the changeset the bookmark points to. In other words, the bookmark 'master' needs to be updated every time you want to push to the Git repository. You can automate the process of moving the bookmark to your latest line of work by activating the bookmark.

hg up master

That's it. Now your working method is:

Work on the repository. Make some commits. Push to the canonical repository Push to Githib Git repository Once the bookmark is active, Mercurial moves the bookmark to your latest line of work automatically.

Short repository name: For your convenience, you can give a short name to your Github repository URL. In your .hg/hgrc update the paths secion:

default = ssh://
github = git+ssh://

Notes: Make sure not to add '.git' directory. Github will not accept the changeset if there is a '.git' directory.