Wednesday, 26 October 2016

One liner for a more readable nslookup output

nslookup is a common command run to verify host name resolution. If we need to check information for a couple of systems, it' s easy.
If we need to validate the details for hundreds of servers then we can run the for loop over the host names and provide the information but it won't be very readable as it'll contains the name of DNS nameserver in every iteration of the loop.
So I created a quick one liner to produce a neat (relatively neat) output.

So, I put the host names in a file named pt2dns like below:

#cat pt2dns
test27367-bkp
test27368-bkp
test27369-bkp
test27370-bkp
test27371-bkp
test27372-bkp
test27373-bkp
test27374-bkp
test27375-bkp
-------------
-------------

Then I ran the below one liner:

for i in $(<pt2dns) ; do echo "server name " `nslookup  $i | awk  '/example/ {print $2}'` "has an IP address" `nslookup  $i | awk  '/172/ {print $2}'` ; done


I did an awk pattern search for the domain name the first time & the subnet name in the second awk pattern search.

This produces the following output:

server name  test27367-bkp.example.com.in has an IP address 172.27.27.202
server name  test27368-bkp.example.com.in has an IP address 172.27.27.203
server name  test27371-bkp.example.com.in has an IP address 172.27.27.204
server name  test27372-bkp.example.com.in has an IP address 172.27.27.205
server name  test27373-bkp.example.com.in has an IP address 172.27.27.206
server name  test27374-bkp.example.com.in has an IP address 172.27.27.207

This is definitely easier to read & copy out in a file/excel work sheet compared to the normal nslookup output.

Tuesday, 25 October 2016

Quick 2 liner to measure used global zone resources

I have a situation where I have a lot of local zones with capped resources running on my global zones.

root@myglobalzone:~# zoneadm list | grep -v global
localzone60051
localzone60043
localzone60063
localzone30025
localzone60049
localzone30061
localzone60039
localzone60105
localzone60101
localzone60161
localzone50059
localzone30081
localzone30035
localzone30083

I need to find the total capped physical memory & the dedicated CPUs used by the local zones so that I can ascertain if the global zone can accommodate more local zones.

I could measure the used capacities by checking the zonecfg for each zone one by one, noting it down & summing the total. That would be a boring and time consuming process.

Here is a quick 2 line trick to get the required information within seconds:

root@myglobalzone:~#  for i in $(zoneadm list | grep -v global); do zonecfg -z $i info dedicated-cpu | grep ncpus | awk '{print $2}'| tr "\n" "+" ; done
16+16+4+48+16+4+16+8+8+8+12+128+32+64+root@myglobalzone:~#

root@myglobalzone:~# echo "16+16+4+48+16+4+16+8+8+8+12+128+32+64+" | sed "s/.$/ /"  | bc
380
root@myglobalzone:~#
root@myglobalzone:~# for i in $(zoneadm list | grep -v global); do zonecfg -z $i info capped-memory | grep physical | awk '{print $2}'| tr "\n" "+" |tr -d "G"; done
16+16+8+64+16+12+16+16+16+16+36+192+32+64+root@myglobalzone:~#

root@myglobalzone:~# echo "16+16+8+64+16+12+16+16+16+16+36+192+32+64+"  | sed "s/.$/ /"  | bc
520

Hope this time saver helps!

Monday, 17 October 2016

Script for identifying multiple disks on a Linux server

This is a short script for identifying 3 PAR disks allocated to a physical server running Linux with multipathing enabled.

Put the disk WWN details provided by the SAN admin in a file called detail.txt.

Now run the following for loop to extract the mpath devices corresponding to the disk WWNs.

#!/bin/bash

for i in `cat detail.txt | awk '{print $3}' |  egrep -v 'showvlun|VV_WWN' | uniq -u`

do

echo "corresponding to 

 `cat detail.txt | awk '{print $3}' |  egrep -v 'showvlun|VV_WWN' | uniq -u | grep -i $i` disk is 
  `multipath -ll | grep -i -A1 $i |awk '{print $1}'` "
  
done

The output of the script is as follows:

corresponding to

 60002AC00000000000004BD20000935D disk is
  mpathv
size=500G
corresponding to

 60002AC00000000000004BD30000935D disk is
  mpatht
size=500G
corresponding to

 60002AC00000000000004BD40000935D disk is
  mpaths
size=500G
corresponding to

 60002AC00000000000004BD50000935D disk is
  mpathu
size=500G
corresponding to

 60002AC00000000000004BD60000935D disk is
  mpathw
size=500G

Primer on Expect scripting


This article is an elementary quick start towards learning expect scripting. Expect is a scripting language used to provide input to an interactive program non-interactively. The most well-known use of expect for UNIX administrators in feeding passwords on the command line non-interactively which can help speed up scripts by miles.

Expect is not installed in the OS by default but is available on the base repo in the OS ISO.

The following  expect commands are used when automating an interactive process over the shell:

  • send – to send the strings to the process
  • expect – wait for the specific string from the process
  • spawn – to start the command
  • timeout - time after which an expect script will exit.
  • set - declare variables for use in the code.


The path for the expect interpreter is /usr/bin/expect.

I'd just like to explore some avenues where us administrators make use of expect to make our life easier.

Common anatomy of an expect script:

#!/usr/bin/expect

##variable declaration (optional)##

##spawn <command> (starting the interactive session)##
##expect "password:" (expect a password prompt)##
##send "password\r" (pass the password string to the prompt non-interactively)##
##expect eof (end of script)##


Example 1: Change a user's password non-interactively.

Here's the code:

#!/usr/bin/expect

set timeout 10

set user [lindex $argv 0]

set password [lindex $argv 1]

spawn passwd $user

expect "password:"
send "$password\r"
expect "password:"
send "$password\r"

expect eof


The test looks like this:

# ./e3.sh testuser 123

spawn passwd testuser
Changing password for user testuser.
New password:
BAD PASSWORD: it is WAY too short
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.


Example 2: Login using expect & start an interactive session

#!/usr/bin/expect

set timeout 1

set login "test"
set addr "centdb"
set pw "123"

spawn ssh -t $login@$addr
expect "$login@$addr\'s password:"
send "$pw\r"

interact


Example 3: Run shell commands within an expect script

#!/usr/bin/expect

set timeout 1

set login "test"
set addr "centdb"
set pw "123"

spawn ssh -t $login@$addr
expect "$login@$addr\'s password:"
send "$pw\r"
expect "$"  # put here string from your server prompt
send "mkdir expect_testing\r"
expect "$" 
send "ls -l expect_testing\r"
expect "$" 

expect eof


Example 4: Using expect inside a bash shell script

#!/bin/bash

expect <<'EOF'

spawn passwd sa

expect "password:"
send "123\r"
expect "password:"
send "123\r"
expect eof

EOF

Example 5: Using expect within a bash shell script to initiate an ssh session

#!/bin/bash

##beginning expect block for entering password non-interactively##
/usr/bin/expect << EOL

set timeout 1
expect <<'EOF'

spawn ssh 192.168.87.129

expect "password:"
send "123\r"
expect "# "
send "uname -a;exit\r"
expect eof
EOF
##end of script##


Example 6: Running an expect one-liner using -c option (interactive session followed)

sa@buntu:~$ expect -c "spawn ssh sa@buntu; expect \"password:\";send \"123\r\";interact"


Example 7: Expect one-liner using -c option in a non-interactive session.

 expect -c "spawn ssh 192.168.87.129; expect \"password:\";send \"123\r\";expect \"# \"; send \"uname -a;exit\r\";expect eof"


The above examples are common uses of the expect script. 

I hope this helps someone somewhere save a lot of time spent entering passwords.

Script to identity & label disks in Solaris

While working with Oracle databases running on Solaris servers, often we come across activities involving storage allocation of multiple disks for usage by the database. Those familiar with Oracle ASM would be aware that for disks to be used by Oracle ASM they must be labeled such that all the disk space is assigned to slice 6 starting from cylinder 1.

This is a small script I wrote to match WWNs to disk names if the storage is being allocated from HP 3PAR storage arrays.

The SAN administrator will usually provide a text file consisting of the WWN details looking something like the small snippet below:

Active VLUNs
Lun VVName               -------------VV_WWN------------- HostName      -Host_WWN/iSCSI_Name-  Port Type Status ID
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      0:2:2 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      1:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      1:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      1:2:2 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      2:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      2:2:2 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      3:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      3:2:2 host active  1
------------------------------------------------------------------------------------------------------------------
  8 total


Copy the contents of the text file into a file on the server & name it detail.txt.

Here is the script:

#!/bin/bash

for i in `cat detail.txt | awk '{print $3}' |  egrep -v 'showvlun|VV_WWN' | uniq -u` 
do

echo "Corresponding to  

`cat detail.txt | awk '{print $2,$3}' |  egrep -v 'Templates|VVName|total|VLUNs|cli%' | uniq -u | cut -d "_" -f2,3,4 | grep $i | sed '/^$/d' ` 

disk is `echo | format | grep -i $i | awk '{print $1,$6}' | egrep -v '3PARdata|scsi|alt'` "

done


The output of this script will be as follows:


Corresponding to

root_desc 60002AC00000000000000BEE0000935C

disk is c0t60002AC00000000000000BEE0000935Cd0: 149.99GB
Corresponding to

bin_desc 60002AC00000000000000BEF0000935C
 
disk is c0t60002AC00000000000000BEF0000935Cd0: 50.00GB


The output prints the VV name, WWN, the matching disk name & the size of the disk. 


To label all the disks in one go, put the names of the disks in a file named disks.txt & run the following for loop:

for i in `cat disks.txt`
do
printf  "p\n0\n\n\n0\n0\n1\n\n\n0\\n0\n6\n\n\n1\n$\nlabel\nyes\nquit\nquit" | format -d $i
done

The above for loop will label all the disks assigning all space to slice 6 starting at cylinder 1.

Monday, 3 October 2016

Troubleshooting the error: "Unexpected failure. Password file/table unchanged." on Solaris 11

I recently did some modifications & a bit of hardening to the zone I whose snapshot I use as a sort of template for other zones. while creating users I found that I wasn't allowed to set their passwords or change passwords of existing users.
I kept getting "Unexpected failure. Password file/table unchanged." when modifying passwords.

root@ztemplate:/etc/default# passwd test
New Password:
Unexpected failure. Password file/table unchanged.

Now, My first instinct from what I've read pointed me to PAM but unfortunately the file /etc/pam.conf was unused i.e. everything was commented.

After a bit of trial & error I found the issue.

It was a misconfiguration in /etc/default/passwd file in the password complexity tunables section:

MINDIFF=3
MINALPHA=2
MINUPPER=2
MINLOWER=2
MAXREPEATS=0
MINSPECIAL=1
MINDIGIT=1
WHITESPACE=YES
MINNONALPHA=1

Actually, MINNONALPHA parameter cannot be used in conjunction with MINSPECIAL & MINDIGIT.

When I commented out MINNONALPHA the parameter I was able to update passwords again flawlessly keeping in line with the password complexity tunables.

Here's a quick description of the above mentioned tunables:

MAXREPEATS
Maximum number of allowable consecutive repeating characters. If MAXREPEATS is not set or is zero (0), the default is no checks

MINALPHA
Minimum number of alpha character required. If MINALPHA is not set, the default is 2.

MINDIFF
Minimum differences required between an old and a new password. If MINDIFF is not set, the default is 3.

MINDIGIT
Minimum number of digits required. If MINDIGIT is not set or is set to zero (0), the default is no checks. You cannot be specify MINDIGIT if MINNONALPHA is also specified.

MINLOWER
Minimum number of lower case letters required. If not set or zero (0), the default is no checks.

MINNONALPHA
Minimum number of non-alpha (including numeric and special) required. If MINNONALPHA is not set, the default is 1. You cannot specify MINNONALPHA if MINDIGIT or MINSPECIAL is also specified.

MINSPECIAL
Minimum number of special (non-alpha and non-digit) characters required. If MINSPECIAL is not set or is zero (0), the default is no checks. You cannot specify MINSPECIAL if you also specify MINNONALPHA.

MINUPPER
Minimum number of upper case letters required. If MINUPPER is not set or is zero (0), the default is no checks.

WHITESPACE
Determine if white space characters are allowed in passwords. Valid values are YES and NO. If WHITESPACE is not set or is set to YES, white space characters are allowed.


I hope this helps someone dealing with this error in the future.

Saturday, 1 October 2016

Managing remote Linux systems with OpenLMI



OpenLMI stands for Open Linux Management Infrastructure. It aims at improving productivity of system administrators by providing a standardized remote API to management functions. OpenLMI was introduced as part of RHEL 7 beta & can be used to manage systems running RHEL, Centos & fedora. Support for other linux variants might be added in the future.

It has the following key features:

  • Configure, manage and monitor storage (local & remote)
  • Configure and manage networks.
  • Install and manage software.
  • Add and manage users.
  • Manage system services.
  • Manage power state.
  • Query system and hardware configuration.
  • System Logging.
  • Active firewall management.
  • Join IPA and MS Active Directory domains.


OpenLMI consists of two components:

  1. LMI metacommand (A command line utility to perform discovery and operations on remote managed systems. For example, it can start a printing service on remote system)
  2. LMIShell (A high-level python-based WBEM client, that can be used for scripting or as an interactive shell to manage remote systems)

When configured OpenLMI works in a server-client model. We configure the server component in the management host & use it to administrator client hosts.

Since this is a lab setup I've shutdown firewalld & set SELinux to permissive.

Installation & configuration:


For the purpose of this demonstration I spun up two CentOS hosts, one to be the server & other to be the client.

Configuring the server/management node:

Install the openlmi-tools & openlmi-scripts packages.

#yum install openlmi-tools openlmi-scripts* -y

you need to have EPEL repository enabled before attempting to install these packages.

Configuring the client node:

On the client to be managed by the server node install the openlmi package.

#yum install openlmi -y

This is a metapackage that installs the OpenLMI infrastructure and a base set of OpenLMI Providers.

Now start the component in charge of receiving instructions (the object broker pegasus)

#systemctl start tog-pegasus.service

To have the service automatically started when the system boots, use the command:

# systemctl enable tog-pegasus.service

We need to give a password to the pegasus user:

#passwd pegasus 


Server client connectivity:

In order to allow the management node to connect to the client node we need to get the certificate for the client node:

# scp 192.168.44.137:/etc/Pegasus/ca.crt /etc/pki/ca-trust/source/anchors/devbox-cert.pem

Add the certificate to the management nodes' trust store:

#[root@instructor ~]# update-ca-trust extract
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit

You can ignore the errors.


Testing:

To test the configuration, type the following command to connect to the client node (devbox in this example)) from the management node (instructor in this example):

[root@instructor ~]# lmi -h devbox

Once connected we are brought into the LMIShell & from here we can gather information about the client node & also perform a plethora of administrative functions on the client.

When we run the first command from the LMIShell we'll need to authenticate with the pegasus user but that's a one time thing.

So, if we need to check the status of sshd service type the following command:

lmi> service show sshd.service
username: pegasus
password:
Name=sshd
Caption=OpenSSH server daemon
Enabled=Yes
Status=Running

If we want to stop & start a service we do by typing service stop <service name> followed by service start <service name>

lmi> service show crond.service
Name=crond
Caption=Command Scheduler
Enabled=Yes
Status=Running
lmi> service stop crond.service
lmi> service show crond.service
Name=crond
Caption=Command Scheduler
Enabled=Yes
Status=Stopped - OK
lmi> service start crond.service
lmi> service show crond.service
Name=crond
Caption=Command Scheduler
Enabled=Yes
Status=Running
lmi>

To list out local storage devices present on a client node type:

lmi> storage list
Name                  Size        Format
/dev/sda              21474836480 MS-DOS partition table
/dev/sdb              5368709120  physical volume (LVM)
/dev/sr0              5368709120  Unknown
/dev/mapper/repo-epel 5364514816  xfs
/dev/sda1             314572800   xfs
/dev/sda2             2147483648  swap
/dev/sda3             19011731456 xfs

To get a list of available commands type ? 

lmi> ?

Static commands
===============
EOF  exit  help

Application commands (type help <topic>):
=========================================
file   hwinfo    locale  power   selinux  sssd     sw      user
group  journald  net     realmd  service  storage  system

Built-in commands (type :help):
===============================
:..  :cd  :pwd  :help


Conclusion:

I've read about OpenLMI being compared to Puppet in some places. I'm not sure how apt is this comparison. More information about OpenLMI can be found on its official website. Some documentation on OpenLMI can be found here.

Using capture groups in grep in Linux

Introduction Let me start by saying that this article isn't about capture groups in grep per se. What we are going to do here with gr...