Change Time Zone on CentOS 7

If time zone is wrong on CentOS, you can come across weird issues. One of the things I came cross is Jenkins grabbing a wrong commit. Gotta fix the time zone.

Check the Current Time Zone

ll /etc/localtime

This command shows which time zone the system is set currently.

How to List Available Time Zones

Let’s list the available time zones.

timedatectl list-timezones

It shows quite a long list of time zones. Let’s grep it so you can find the one you want.

timedatectl list-timezones | grep Lo

It lists time zones that contains “Lo”. The time zone I want to use is America/Los_Angeles. I’m going to set the time zone to it.

Change the Time Zone

I’m going to change the time zone to America/Los_Angeles.

sudo timedatectl set-timezone America/Los_Angeles

Execute date command to check the current date, time and time zone.

Thu Oct 31 18:57:05 PDT 2019

Building Bash Muscle (13)

Let’s talk about some cook tips with the terminal. These tips are not directly related to bash itself but very useful tips

Ctrl+L will clear the screen but it does not clear the buffer. If you scroll up, you get to see the previously executed command result.

If you do Ctrl+A, the cursor will move to the beginning of the line. You can accomplish the same thing with Home button.

Ctrl+Right Arrow lets you move the cursor forward by a word. Ctrl+Left Arrow lets you move the cursor backward by a word.

Alt+U capitalizes all the letters after the cursor. Alt+L lowers all the letters after the cursor.

Ctrl+S stops output of the screen and Ctrl+Q resumes it.

!! repeats the last command.

Alt+D removes the word right after the cursor. Ctrl+K removes everything after the cursor. Ctrl+U removes everything before the cursor.

These tips and tricks should make your bash life a little more productive. 🙂


Building Bash Muscle (12)

I will introduce a command mktemp. According to the man page “mktemp – create a temporary file or directory”.

Let’s create a temp file and write some text in it.

$ tmpfile=$(mktemp)
$ echo $tmpfile
$ echo 'hello temp file' >> $tmpfile
$ cat $tmpfile
$ rm -rf $tmpfile
  1. The first line executes mktemp command and sets the temporary file path into tmpfile variable.
  2. The second line prints the path of the temp file path.
  3. The third line adds the text ‘hello temp file’ into the temp file.
  4. The fourth line prints out the content of the temp file. The last one removes the file.

Now let’s create a temp directory.

$ tmpdir=$(mktemp -d)
$ touch $tmpdir/foo.txt
$ echo 'hello foo text' >> $tmpdir/foo.txt
$ cat $tmpdir/foo.txt
$ rm -rf $tmpdir
  1. The first line creates a temp directory and sets the temp directory path to tmpdir variable. The -d option tells mktemp to create a temporary directory.
  2. The second line creates foo.txt in the temporary directory.
  3. The third line adds ‘hello foo text’ to the text file.
  4. The fourth line prints the content of the foo.txt file under the temp directory.
  5. The fifth line removes the temp directory along with the foo.txt file underneath it.

To recap, mktemp can be used to create a temporary file or directory safely to work with them for possible atomic processing.

Building Bash Muscle (11)

This article is going to be pretty basic but it’s always good to go back to the basics.

You can create a new directory like this.

mkdir foo1

That was too easy. What if you want to create multiple directories at a time?

mkdir foo1 foo2 foo3

That’s all good but what if you want to create a tree structure? like foo1/foo2/foo3? Use the -p option to create a tree structure.

mkdir -p foo1/foo2/foo3

-p option is “no error if existing, make parent directories as needed” according to the man page. Here is the tree view of the directory structure that was just created by the command.

What if you want to remove foo1? rmdir command is available to remove a directory.

rmdir foo1

That didn’t work… What happened?

Well, if there is any object such as sub directory or file in a directory, you rmdir cannot remove the directory. If you read the man page for rmdir, the first line says “rmdir – remove empty directories”.

If you want to remove all foo1/foo2/foo3 directories, here is what you can do with rmdir.

rmdir -p foo1/foo2/foo3

Hmm, this is still cumbersome. I want to be able to express it like “rmdir foo1” and remove everything including files and sub directories under foo1. Here is what you can do.

rm -rf foo1

rm -rf is really powerful so be careful when using it.

If you want to remove everything in a directory, execute the following command.

rm -rf thediriwannaempty/*

To recap, we went over how to create and remove directories in bash.


Configuring JavaFX Project on IntelliJ

I’ve had a hard time just to get a JavaFX project going with IntelliJ on Java 11. After spending 2 nights of digging and Googling, I finally got “Hello World” window to show up.

I will try to summarize what I have done.


I have decided to manage dependencies and build with maven. Here is the pom.xml file I created. Right click on the project in Project window and select All Frameworks Support to add Maven support to the project.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=""



VM options

I’m sure the module path may be different depending your installation but here is the VM options I gave in Run/Debug Configurations. (Run -> Edit Configurations) This is necessary because JDK does not contain JavaFX by default anymore.

--module-path "/usr/share/openjfx/lib" --add-modules javafx.controls,javafx.fxml


Navigate to File -> Project Structure -> Project. Make sure you select 11 – Local variable syntax for lambda parameters in Project language level.

Language Level

Navigate to File -> Project Structure -> Modules. Select 11 – Local variable syntax for lambda parameters for Language level in Sources tab.11 - Local variable syntax for lambda parameters

Target bytecode version

Navigate to File -> Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler. Select 11 for Target bytecode version.

Target bytecode version


There are many options to create cross platform desktop applications and JavaFX is one of them. I hope JetBrain will streamline the way to create JavaFX project easily in the future. I have uploaded the code to my GitHub repository.

Love Linux

I love Linux. It’s been quite a long way with computing. I had been a hard core Windows guy until about 15 years ago. I went for Mac OS X (remember eMac?) and then to Hacintosh for about 10 years. Then I was spending way too much time hacking just to get the system to work, so I went for Linux Mint. I was already using Linux Mint for my media server in my living room, so I had no hesitance there.  I do still use Windows on a VM and my company provided work laptop is an HP Windows machine, but my daily driver at home is Linux Mint.

This guy Bryan Lunduke has such an enthusiasm for Linux. I listen to his YouTube podcast quite often. He seems to live in NW area and so do I. I hope to see him some day. 🙂

This one is one of my favorite. Linux runs everywhere even on a cow milking machine and that is awesome! 😀

Building Bash Muscle (10)

In the 10th “Building Bash Muscle” series, I’m going back to sed and introducing tail. There are times when you need to read a big log file. I will peek at /var/log/syslog

The whole big log file should not be read into memory for an obvious reason. sed can be used to read part of the big file. Let’s read the 100th line of syslog with sed.

$ sed -n '100 p' /var/log/syslog

You can use the following command to read from 100th to 110th line.

$ sed -n '100,110 p' /var/log/syslog

You probably would not know which line to read but the practical situation would be you want to read the last 20 lines of the log file. You can use tail to accomplish it.

$ tail -n 20 /var/log/syslog

You can, of course, grep the result of the tail and narrow down the result further for analysis.

To recap, sed and tail can be used to get a part of big files.

How to Make Jenkins Request User Data Available as an Environment Variable

Jenkins jobs serves many purposes. One of the important ones is to use them as self service type of jobs. Usually, you make them available to internal customers. When there are issues, the first thing you want to know may be who requested the job.

I know there is a plugin that makes BUILD_USER_ID available as a environment variable, but I will show you a little trick that doesn’t require another plugin.

First go to Configure section the job you are working on. Click Inject environment variables to the build process under Build Environment section.

Copy and paste the following code in Groovy Script section.

def map = ["REQUEST_USER": currentBuild.getCauses()[0]['userId']]
return map

When you run a build, the REQUEST_USER environment variable is available throughout your build. This is very convenient for logging purposes.  If you check the Environment Variables page for the build the key and the value are there.

Describing it in Job DSL, it looks like the following.

job('foo') {
    environmentVariables {
        groovy('''def map = ["REQUEST_USER": currentBuild.getCauses()[0]['userId']]
return map''')


Building Bash Muscle (9)

Let’s replace a text with some other text. I’m going to replace ‘hello’ in ‘hello world’ with ‘hi’. The result will be ‘hi world’. I’m going to have ‘hello world’ in a variable.

var1='hello world'
echo $var1

The following code replaces hello with hi and print the result out in the terminal.

echo ${var1//hello/hi}

You can alternatively use regular expression.

var2='food moon red green monster'
echo ${var2//?oo?/whatever}

The result looks like the following.

whatever whatever red green monster

To recap, the syntax is ${variable//replacefrom/replaceto}

Automating CentOS 7 Joining Windows Domain in bash

I previously wrote an article about CentOS 7 joining a Windows domain. I have come up with a way to automate it in bash script. It’s time for me to utilize my bash muscle I built in the past. 🙂 Here is the script. Make sure to execute it as root.

set -e
set -u

while getopts "u:p:d:g:" arg;
	case $arg in
		u) username=$OPTARG;;
		p) password=$OPTARG;;
		d) domain=$OPTARG;;
		g) sudoergroup=$OPTARG;;
		\?) echo "Invalid option -$OPTARG" >&2;;

yum install sssd realmd oddjob oddjob-mkhomedir adcli samba-common samba-common-tools krb5-workstation openldap-clients policycoreutils-python -y

echo "Joining $domain"
echo "$password" | realm join --user=$username $domain


echo "Modifying $sssd_conf_path"
sed -i 's/use_fully_qualified_names = True/use_fully_qualified_names = False/g' $sssd_conf_path
sed -i 's/fallback_homedir = \/home\/\%u@\%d/fallback_homedir = \/home\/\%u/g' $sssd_conf_path

echo "Restarting sssd"
systemctl restart sssd

echo "Granting $sudoergroup to be sudoers"
sudoergroup=${sudoergroup// /\\ } #replace space with \space
echo "%$sudoergroup@$domain ALL=(ALL) ALL" >> /etc/sudoers.d/sudoers

echo "Completed joining $domain"

Make sure that -u indicates a domain user that has a permission to have computers join the domain. Execute the script like the following example.

./ -u 'domainadminuser' -p 'yourpassword' -d '' -g 'domain admin'

This bash script really eliminates all the manual steps to join a CentOS 7 to Windows domain. This script can be used on pretty much all the Red Hat based Linux distributions.