HOWTO: IBM DB2, ODBC, and Linux (*nix) configuration

The DB2 ODBC driver works like anything else IBM. Nonstandard to the rest of the universe. How to set up ODBC:

Unix admin needs to do:
Retrieve the config file locations:

$ odbcinst -j
unixODBC 2.2.14
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/jason/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

Add/update the following lines in the /etc/odbcinst.ini file (or wherever the file is as reported by odbcinst -j):

[DB2]
Description = DB2 Driver
Driver = /opt/ibm/db2/db2_v9.7/lib64/libdb2o.so
fileusage=1
dontdlclose=1

The driver line should point to the full path of libdb2o.so (any *nix but aix) or libdb2o.a (aix).

DBAs need to:
Add/update the following lines to the ${IBM_DB_DIR}/sqllib/cfg/db2cli.ini file for each database that uses odbc:

[MYDB2DB]
Database=MYDB2DB
Protcol=TCPIP
Hostname=mydbhost
ServiceName=67033

Add/update the following lines in the ${HOME}/.odbc.ini file:

[MYDB2DB]
Driver=DB2

Make sure we’re using the unixODBC isql:

$ /usr/bin/isql --version
unixODBC 2.2.14

Validate using unixodbc “isql”:

$ /usr/bin/isql -v MYDB2DB testuser test_password
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL>

The DSN for the entry is simply “dbi:ODBC:MYDB2DB” if you’re using Perl. Later versions of the db2 client allow you to specify the connect options in the DSN like so:

my $odbc_connect_str = "dbi:ODBC:"
               . "DRIVER=/opt/ibm/db2_v10.5/lib64/libdb2o.so;
               . "Protocol=tcpip;"
               . "Hostname=mydbhost;"
               . "Port=67033;"
               . "DATABASE=MYDB2DB";
Share Button

Apple OSX 10.2 on Linux using the PowerPC CPU emulator Pear

I was able to get OS X 10.2 (PowerPC) running in Pear (PowerPC emulator for Windows and Linux) on Kubuntu 16.10 🙂

I need to set up the tun0 interface in order to get networking (internet) working.

PearPC Linux host setup
vde_tunctl — create and manage persistent TUN/TAP interfaces

Why? Because I can

Share Button

SOLVED: SSH and Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)

OpenSSHI ran across the error “Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).” while ssh’ing to another server today:

$ ssh myhost
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

Usually this means that the permissions of ~/.ssh, ~/.ssh/authorized_keys or your home directory on the other box isn’t setup right The permissions should look like so:

  1. -rwx——. /home/jason
  2. -rwx——. /home/jason/.ssh
  3. -rw——-. /home/jason/.authorized_keys

You would fix with:

$ chmod 0700 ~
$ chmod 0700 ~/.ssh
$ chmod 0600 ~/.ssh/authorized_keys

In my case, the permissions were correct. I ran the ssh command with extra verbose (-v -v)

$ ssh -v -v myhost
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /home/jason/.ssh/config
debug1: Applying options for *
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: /etc/ssh/ssh_config line 62: Deprecated option "RhostsAuthentication"
debug2: ssh_connect: needpriv 0
debug1: Connecting to myhost [192.168.12.6] port 22.
debug1: Connection established.
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /home/jason/.ssh/id_rsa type 1
debug1: identity file /home/jason/.ssh/id_rsa-cert type -1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /home/jason/.ssh/id_dsa type 2
debug1: identity file /home/jason/.ssh/id_dsa-cert type -1
debug1: identity file /home/jason/.ssh/id_ecdsa type -1
debug1: identity file /home/jason/.ssh/id_ecdsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_6.0
debug1: match: OpenSSH_6.0 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.3
debug2: fd 3 setting O_NONBLOCK
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib
debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit: first_kex_follows 0
debug2: kex_parse_kexinit: reserved 0
debug2: kex_parse_kexinit: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: none,zlib@openssh.com
debug2: kex_parse_kexinit: none,zlib@openssh.com
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit: first_kex_follows 0
debug2: kex_parse_kexinit: reserved 0
debug2: mac_setup: found hmac-md5
debug1: kex: server->client aes128-ctr hmac-md5 none
debug2: mac_setup: found hmac-md5
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug2: dh_gen_key: priv key bits set: 154/256
debug2: bits set: 520/1024
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
Warning: Permanently added 'myhost,192.168.1.66' (RSA) to the list of known hosts.
debug2: bits set: 525/1024
debug1: ssh_rsa_verify: signature correct
debug2: kex_derive_keys
debug2: set_newkeys: mode 1
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug2: set_newkeys: mode 0
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug2: service_accept: ssh-userauth
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug2: key: /home/jason/.ssh/id_rsa (0x7ff594d8ecb0)
debug2: key: /home/jason/.ssh/id_dsa (0x7ff594d90550)
debug2: key: /home/jason/.ssh/id_ecdsa ((nil))
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: No more authentication methods to try.
Permission denied (publickey,password,keyboard-interactive).

I didn’t see a reason why I wasn’t getting a password prompt but I do see it reading my ssh_config file. A real quick override of the ssh_config showed me that my ssh_config was the culprit:

$ ssh -F /dev/null myhost
jason@myhost's password:

So what is in my ~/.ssh/config file?

ServerAliveInterval 240
BatchMode yes
TCPKeepAlive = yes

Neither ServerAliveInterval or TCPKeepAlive have anything to do with authentication but BatchMode does. From the ssh_config man page:

BatchMode

The argument must be yes or no. If set to yes, passphrase/password querying will be disabled. This option is useful in scripts and other batch jobs where you have no user to supply the password.

So, if my public ssh key is not in the ~/.ssh/authorized_keys, the connection will fail with a permission denied. Let’s verify but removing BatchMode from the ~/.ssh/config file:

ServerAliveInterval 240
TCPKeepAlive = yes
$ ssh -F /dev/null myhost
___$

Success 🙂

Share Button

OpenVPN & Network Manager: selecting a random VPN target each time you start the Virtual Private Network (UNIX/Linux) SOLVED

I sometimes perform some IT work for a nonprofit organization. They use OpenVPN for their network but since they reside in different locations, they have multiple OpenVPN servers set up rather than just one point of entry. The problem I’ve noticed is that at times one or another will be slower. While I don’t have a mechanism to identify which is faster, I can roll the dice and have my vpn start script pick a random server instead of me having to randomly pick one myself.

#!/bin/bash

# If the network card is unavailable, we're not going to bring up the vpn
REQUIRED_CONNECTION_NAME="enp0s8"

# VPN_LIST is just a simple array
declare -a VPN_LIST

# BASH arrays start with index 0
i=0

# read the vpn list into an array
while read TMP_VPN; do
    VPN_LIST[$i]="$TMP_VPN"
    ((i++))
done < vpns.txt 

# if the vpns.txt is NOT empty
if (( i >= 0 )); then
    # Choose a random VPN index from the TMP_VPN array
    if (( i > 0 )); then
        ((i - 1))
        ((RANDOM_VPN = $RANDOM % $i))
    else
        RANDOM_VPN=$i
    fi

    # We set the VPN_CONNECTION_NAME to the VPN we chose
    VPN_CONNECTION_NAME=${VPN_LIST[$RANDOM_VPN]}

    DEFAULT_CONNECTION=$( nmcli con show --active |grep "${REQUIRED_CONNECTION_NAME}" )
    VPN_CONNECTION=$( nmcli con show --active | grep "${VPN_CONNECTION_NAME}" )

    # Make sure that the vpn connection isn't already up
    if [[ "${DEFAULT_CONNECTION}" != "${VPN_CONNECTION}" ]]; then
        echo -n "Connecting to ${VPN_CONNECTION_NAME} ... "

        # The credentials are stored in my Gnome keyring so I run the nmcli command as jason
        su - jason -c "nmcli con up id \"${VPN_CONNECTION_NAME}\""

        RC=$?

        if (( RC == 0 )); then
            echo "SUCCESS"
        else
            echo "FAILED"
        fi
    else
        echo "configuration mismatch"
        RC=1
    fi
fi

exit $RC

The file vpns.txt is simply a text file with the names of the VPNs as they are listed in OpenVPN (see /etc/NetworkManager/system-connections for the list of defined VPNs). One VPN per line.

vpn-east.example.org
vpn-west.example.org
vpn-europe.example.org
vpn-tokyo.example.org
Share Button

HOWTO determine if a shell script is being sourced or executed directly

Every once in a while you need to source a script file, such as .bashrc, but you don’t want someone to run it directly because when you run it directly it will run in a subshell. Any environment variables declared in a subshell will NOT propagate back up to the calling process.

The test_source_this script that will be sourced/executed:

if [[ "X$(basename -- "$0")" == "Xtest_source_this" ]]; then
   echo "test_source_this is being called directly"
else
   echo "test_source_this is being sourced"
fi

The calling script that sources the test_source_this script:

#!/bin/ksh

. ./test_source_this

Executing the test_source.ksh script shows that we are indeed sourcing the test_source_this script:

$ ./test_source.ksh
test_source_this is being sourced<

If we call the test_source_this script directly we will receive the expected result:

$ ./test_source_this
test_source_this is being called directly
Share Button

Korn Shell 93: A better if structure with many tests

Writing korn shell scripts you will often come across if structures that look something like the following. It works well but the if structure doesn’t lend itself for quick reading.

if [[ MYVAR != "potato" ]] && [[ MYVAR != "acorn" ]] && [[ MYVAR != "pizza" ]] && [[ MYVAR != "apple" ]]; then

We can make it far more readable without losing the functionality:

if [[ MYVAR != @(potato|acorn|pizza|apple) ]]; then

The “@(potato|acorn|pizza|apple)” is effectively a short cut to a case structure. So, let’s expand that to the full case statement:

case ${MYVAR} in
    !potato|acorn|pizza|apple)
        # commands go here
        ;;
esac
Share Button

Getting Flickr::API to work on Ubuntu Linux SOLVED

In order to use the Flickr::API example by Gabor Szabo, I needed to create a LWP object specifying the path to the system certificates when creating the Flickr::API object.

Works:

my $flickr_api = Flickr::API->new( {
    key       => $key,
    # secret  => $secret,
    unicode   => 1,
    lwpobj    => LWP::UserAgent->new(
        ssl_opts => { 
            SSL_ca_path => '/etc/ssl/certs',
        },
    ),
}); 

Doesn’t work Perl(reports a 500 error with “Can’t connect to api.flickr.com:443 (certificate verify failed)” ) :

my $flickr_api = Flickr::API->new( {
    key       => $key,
    # secret  => $secret,
    unicode   => 1,
    ssl_opts  => { 
        SSL_ca_path       => '/etc/ssl/certs',
    },
});

You could use Mozilla::CA as brian d foy suggests but the bundled file is from 2014. Personally, I’ll use the certificate files from the OpenSSL project. 🙂

Share Button

HOWTO: Enable 3D Acceleration in VMWare Player/Workstation in Ubuntu Linux 15.04 with Intel Graphics SOLVED

When youVMware start a virtual machine using VMWare Workstation or Player and receive a warning saying 3D Acceleration is not available, you can easily enable it. All you need to do is add a single line to the .vmx file (e.g. “Fedora Linux.vmx”):

mks.gl.allowBlacklistedDrivers = "TRUE"
Share Button

Creating an ebook (epub) using Quickly on Ubuntu Linux

I ran across Mike Hingley‘s video on Youtube and had to share 🙂

Share Button

Perl: Sourcing a profile or bashrc or other shell script SOLVED

Everyone has worked at Perla place where they do things slightly different than what you’re used to. In this case we need to source a shell script file that houses the environment variables that we need to import. Unfortunately, the shell script file may or may not call other scripts/programs or it may use string manipulation to populate the environment variables. This means you can’t just read a the file in perl with simple key/value pairings.

In the Unix/Linux shell scripting world, if you export an environment variable it will be available in any child process.

# Here we export the variable so it will show up in Perl's %ENV hash:
export MYVAR="woohoo"

If we don’t explicitly export the environment variable, it will not be available to a child process.

# We don't export the variable so it will not show up in Perl's %ENV hash:
NOTEXPORTED_VAR="too bad"

So how do we handle the non-exported environment variables so Perl can use them? Each shell that is POSIX compliant in one way or another will have the set builtin command that will produce output of the environment variables regardless of whether they’ve been exported. Fortunately for us, it is in key/value pairs with an equals sign “=” as the delimiter. Be warned, you will get everything.

In the example code below we’re going to use the BASH shell to source the /somedir/.env file. You can replace it with the shell of your choice. Setting an environment variable with Perl’s %ENV hash will automatically export it making it available for any child processes of the Perl process.

 BEGIN {
     # you will need to include the "&& set" *IF* you have an shell file
     #  that doesn't export the variables.  
     if ( -f '/somedir/.env' && -x '/somedir/.env') {
         open(my $PS, 'bash -c ". /somedir/.env && set" |') or die 'Cannot execute bash built-in set');

         while (< $PS>) {
             # we need to strip extended ASCII characters
             #  and any lines without an "="
             if (/=/ && /[^\x20-\x7F]/) {
                 chomp;
                 my ($key, $value) = split /=/;
                 $ENV{$key} = $value;
             }
         }

         close $PS;
     }
Share Button