Enabling mkhomedir on Ubuntu for FreeIPA

The story

In my endeavors to practice with FreeIPA, I tested the Ubuntu port of freeipa. There is a known bug where the –mkhomedir option of the ipa-client-install command for Ubuntu does not actually enable making homedirs for users on first login.

The solution

apt-get install freeipa-client
th="$( hostname --fqdn )"; case "${th}" in *.*) :;; *) th="${th}.$( awk '/search/ {print $2}' /etc/resolv.conf )";; esac;
ipa-client-install --mkhomedir --force-ntpd --enable-dns-updates --hostname "${th}"
sed -i -r -e 's/Default:\s\w+/Default: yes/;' /usr/share/pam-configs/mkhomedir
pam-auth-update # and add the homedir option manually because it cannot be scripted.



  1. https://bugs.launchpad.net/ubuntu/+source/freeipa/+bug/1336869

Inject hostname into kickstart

The story

I have been learning how to automate my centos installations in my virtual environment. I’ve learned how to use the virsh command line to spin up a new vm the way I like, and to feed it a kickstart file. I also learned how to use kickstarts.

Set hostname automatically with a kickstart

In the main area of the kickstart file, include this line:

%include /tmp/network.ks

Include in your %pre section this section:

echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname renameme.ipa.example.com" > /tmp/network.ks
for x in $( cat /proc/cmdline );
   case $x in SERVERNAME*)
      eval $x
      echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname ${SERVERNAME}.ipa.example.com" > /tmp/network.ks

To paraphrase the post I’m duplicating for myself, you need the first echo redirection to the file in case there was no SERVERNAME= parameter given to the kernel.
When you boot, you need to include on the kernel command (usually the “linux” one), the value SERVERNAME=myhostname.

For my virsh command, that is:

vm=centos7-02a ; virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=rhel7.2 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/CentOS-7-x86_64-Minimal-1511.iso  --initrd-inject=/mnt/public/Public/centos7-ks.cfg --extra-args "ks=file:/centos7-ks.cfg SERVERNAME=${vm}" --debug --network type=direct,source=eno1


  1. Install system-config-kickstart on Fedora 25 http://bytefreaks.net/gnulinux/fedora-25-workaround-to-install-system-config-kickstart
    sudo dnf install
    https://kojipkgs.fedoraproject.org/packages/system-config-date/1.10.9/3.fc25/noarch/system-config-date-1.10.9-3.fc25.noarch.rpm python-kickstart system-config-kickstart;
  2. https://sysadmin.compxtreme.ro/automatically-set-the-hostname-during-kickstart-installation/

List available packages from one repository

For dnf

dnf list available --disablerepo=* --enablerepo=reponame

For dpkg (low-level package manager for apt)

ff() { for file in /etc/apt/sources.list.d/$1.list; do grep -iE "Package:" "/var/lib/apt/lists/$( cut -d' ' -f2 "${file}" | sed -r -e 'sX\/X_Xg;' -e 's/\<http.__//g;')Packages"; done; }
ff reponame

The story

For some reason it is harder to manage packages with apt: This is a main reason I don’t like to use it. I had to go write this crazy one-liner function to accomplish the same task that dnf provides with just two flags.
Also, the apt command here shows all the packages from that repository, regardless of its installed state. The dnf command will show only the ones available that are not already installed.

Using Google Talk Plugin in Palemoon Portable in Wine on Linux


My main browser is Palemoon Portable which I run in Wine on GNU/Linux. I also use Gmail, Google Talk (the pre-Hangouts tool), and Google Voice.

In order to make and receive phone calls from my main web gmail page, I used this process.

  1. Install Adobe Flash Player for Firefox on Windows. I used the offline installer from the download link at Weblink 2.
    1. Used my Linux native Firefox to navigate to the normal Adobe flash player download page.
    2. Selected “Need Flash Player for different computer?”
    3. Selected Windows 7/Vista/XP and FP 25 for Firefox – NPAPI.
    4. From a terminal, I ran the following command and installed Flash like normal.wine ~/Downloads/install_flash_player.exe
  2. Install Google Talk plugin.
    1. Unfortunately the gmail link for “Download voice chat plugin” failed to complete. When I ran wine ~/Downloads/GoogleVoiceAndVideoSetup.exe from a terminal, I observed that the process failed because of some network issue related to wine:fixme:secur32:schannel_get_cipher_algid unknown algorithm 23
      fixme:secur32:schannel_get_mac_algid unknown algorithm 200

      I bet it has something to do with the way my GNU/Linux computers always have some long MAC address in my dhcp list instead of a normal 12-character value. I don’t know how to fix that, nor was I able to trick the installer to continue.
    2. So I had to install the Google Talk plugin manually.
      1. I used a Windows computer that already had a working environment of Google Talk for Palemoon Portable. I copied these files:C:\Users\bgstack15\AppData\Roaming\Mozilla\plugins\npgoogletalk.dll
        To location
        Where /usr/share/PMP257 is my D:\PortableApps location.
      2. I also copied this entire directory:C:\Users\bgstack15\AppData\Local\Google\Google Talk Plugin\
        As the directory
        /usr/share/PMP257/Lib/Mozilla/Plugins/Google Talk Plugin/
      3. I set up the wine registry with a key and values from a registry file as seen below.tf=/usr/share/PMP257/Lib/Mozilla/Plugins/googletalk.reg
        touch "${tf}"; chmod 0644 "${tf}"
        cat << EOF > "${tf}"
        [HKEY_CURRENT_USER\Software\Google\Google Talk Plugin]
        "install_dir"="z:\\usr\\share\\PMP257\\Lib\\Mozilla\\Plugins\\Google Talk Plugin\\"
        regedit "${tf}"

        If the registry file does not import properly, try sticking a blank line after REGEDIT4. WordPress and the html <code> tag do not play nicely together with blank lines in code.


This entire process was made possible by the fantastic users of the Portableapps.com community: portablealpha, taosk8r, acamp, and robertcollier4. It was that one page (weblink 1), and my working but disused Windows installation that made this whole process possible.


I realize I make life hard for myself, for using a web interface in a portable version of a small fork of a web browser in an emulator.

The story behind why I use this portable browser, in wine, on Linux, is this. When I first started getting on the Internet, I was a teenager and did not own my own computer. I had a flash drive, and I used it to store my personal files. I discovered PortableApps which let me use probably Firefox 2 or 3 from my flash drive. Even as I grew and got my own computers, I still kept my main web browser as a portable one so it would be relatively free from OS hooks so it was easy to transplant from system to system, as I migrated my main workstation. I built up a new installation every couple of years, hopping from Firefox 17 at one point to 27 to 33 to 38. After that, I switched to Palemoon 25 Portable and that is what I’m still on as of this post.

Now, 2016 was the Year of Linux on the Desktop for me, as I wanted to avoid the Windows 10 debacle. I had installed Korora 22 Cinnamon on a spare laptop in November of 2015 and from there made it my main system. In February of 2016 I copied over my Palemoon Portable install and it ran in Wine just fine! The only problem it had was it didn’t work with Google Voice.

This week I was trying to solve a VLC dlna problem where it was not finding my Plex server. I got frustrated with that (a bug that’s still unresolved https://bugs.launchpad.net/ubuntu/+source/libupnp/+bug/1571199) and transitioned into looking into the Google talk problem on Palemoon Portable.



  1. Entire portableapps thread explaining how to get a PortableApp to use Google Talk. http://portableapps.com/node/24945

Portablealpha on September 15, 2010 – 9:18pm

Adding Google Voice plugin

Just wanted to let people know how I got the Google Voice plugin to work so that I could use the “Call Phone” feature from within gmail. This is *not* elegant but it’s the only way I could figure it out because the target computer is behind some nasty firewalls (and the Google Voice installer isn’t allowed to call home to download its files).

1. Install the Google Voice plugin on your home computer.
2. Locate the Google Voice and Video Accelerator plugins in FF using about:plugins.
3. Copy those to your Firefox Portable plugins directory on the flash drive.
4. Locate the “Google Talk Plugin” folder on your hard drive and copy it to the flash drive (doesn’t matter where).

When you want to use Google Voice through Firefox Portable, run the exe in the Google Talk Plugin first, then start FFP and go to gmail. Note that once you exit gmail, it will stop the exe, so you’ll have to run it again manually if needed.

Anyone have any suggestions to automate this?

Taosk8r on June 11, 2011 – 1:42am

Oh good

I found this thread again.. I cant seem to find where ff 4.0 puts these.. the info I get is:



Is this even still relevant?

Acamp on October 21, 2011 – 3:13am


Works like a charm!

You have to search your computer for those two files (real pain in the ass on newer windows machines because they try not to display any scary system files). Once windows can’t find it, click advanced, check include non-indexed, hidden and system files.

You also need to search for the folder “Google Talk Plugin” and copy that to the flash drive. It contains the executable that needs to be launched before Firefox is opened

Robertcollier4 on September 28, 2012 – 7:33am

Works without needing to load the EXE manually

Create the following directory structure if not already existing:

Place the following files/folders in Plugins directory:
“Google Talk Plugin” (complete folder)
“Google Talk Plugin Extras” (complete folder)

The files are located at:
DocsandSettings\Username\Local Settings\Application Data\Google\Google Talk Plugin\
DocsandSettings\Username\Application Data\Mozilla\plugins\

Then it will work and the EXE will automatically load from Gmail.

Robertcollier4 on September 30, 2012 – 2:02pm

Specify path in registry to load EXE automatically

Hi – there is one update. If you want the EXE to run automatically, you must add the following registry key with the proper path to googletalkplugin.exe so that it knows where to find it and load it automatically. It will work without adding the registry path – but if the registry path is not there as shown below then you must run the googletalkplugin.exe manually before loading the browser.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Google\Google Talk Plugin]
“install_dir”=”D:\\FirefoxPortable\\Data\\Plugins\\Google Talk Plugin\\”

  1. https://get.adobe.com/flashplayer/download/?installer=FP_25_for_Firefox_-_NPAPI&stype=5513&standalone=1
  2. Normal adobe flash player download page https://get.adobe.com/flashplayer/

Installing Korora 25 xfce in qemu/kvm


I wanted to install a Linux virtual machine on my Linux laptop. Already installed was virtual machine manager. For the time being, my host OS is Fedora 25 KDE and what I wanted to run in the vm is Korora 25 xfce. All this because I don’t know how to have two different versions of Teamviewer run at the same time.


I downloaded the K25 xfce iso and then started the “Create a new virtual machine” wizard. The process was simple enough (minus scraping out enough disk space on my host). I ran into an issue with interacting with the virtual machine, though. During the install, I had to switch my display to VNC server type.

And even then, my mouse location was not aligned the cursor during the entire process. It’s a good thing Anaconda works with keyboard input! I was actually quite impressed because I’ve had trouble with keyboard input in anaconda for CentOS 7. But for Korora 25 it was fine.

Once I installed and rebooted, I switched the display back to “Spice server” and then everything worked smoothly: keyboard and mouse. Maybe I missed some guest additions package or something, because my screen doesn’t resize automatically with the window of the display. But selecting a different screen resolution in the xfce display utility worked just fine!

Linux use tee with color

Output in color on the console

The console normally can display color. The most obvious example is when you do a standard ls command. By default on most systems, ls includes a –color=auto flag that changes filenames of certain types to different colors.

Some applications display colorized output like systemctl status nfsd.service.

Using tee

Tee is a nifty cli utility that duplicates the input to both the standard out as well as to a file. You can use it like so:

ls -l --color=always | tee ~/ls.out

Some tools will disable colorized output if it is going to a pipe, but ls can be forced to provide color with the –color=always flag. For applications that don’t have such an option, you can usually prepend the command unbuffer.

unbuffer ansible-playbook playbook.yml | tee ansible.log

When you examine the file, however, you will observe that the console color commands were saved. That’s perfectly fine if you cat the file, or less -R, but normally you want a text file to just have the text. Sysadmins are quite used to dealing with logs that are all the standard color of the console.

The solution: ctee!

Using some fantastic resources on the Internet which I list at the bottom of this post, I assembled a tool that will tee the input, and send color to the stdout (usually the console) and send regular text to the file. I call my creation ctee.

Code walkthrough

So this script was generated using newscript which copies the template from the same bgscripts package. The template sources framework, which is my big flagship library of functions for shell scripts.

Lines 39-54 are the parseFlag function, which parses the command line passed parameters. I implemented this before I ever learned about Python’s argparse library.
The only flag worthy to note is –append. All it does is set the variable to 1.

The meat of this script starts at line 85 and goes to the end, which is shown below.

# this whole operation calculates where the stdout of this whole pipe goes
_fd1="$( readlink -f /proc/${_pid}/fd/1 )"
while test ${ttyresolved} -lt 10;
   ttyresolved=$(( ttyresolved + 1 ))
   echo "before ${ttyresolved}, _pid=${_pid}, _fd1=${_fd1}" > ${devtty}
   case "${_fd1}" in
      *pipe:* )
         newpid=$( find /proc -type l -name '0' 2>/dev/null | xargs ls -l 2>/dev/null | grep -F "$( basename ${_fd1} )" | grep -viE "\/${_pid}\/"; )
         newpid=$( echo "${newpid}" | head -n1 | grep -oiE "\/proc\/[0-9]*\/" | grep -o "[0-9]*" )
         _fd1="$( readlink -f /proc/${_pid}/fd/1 )"
       *dev*|*/* )

echo "thisttyout ${thisttyout}" > ${devtty}

case "${append}" in
      tee ${thisttyout} | sed -u -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" >> "${outfile1}"
   *) tee ${thisttyout} | sed -u -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" > "${outfile1}"

The idea behind ctee is that it uses tee, but inverts the outputs. Ctee uses the console tty as the file to output to, and then standard out continues on to a sed command that strips out the console color escape sequences which is then redirected to the file specified to ctee as a parameter.

So one of the big tricks is to derive which console you are executing this command from. The while loop from lines 90-106 use a /proc filesystem trick to find the process on the other end of a pipe. This loop travels from this process’s standard out to the standard in of another process, and then takes that standard out, and tracks that down until it includes the phrase “dev” or “/” in its name, indicating either a tty or a file (technically the dev is redundant, but it makes the line easier to understand).

The second main trick of ctee is that it has a sed command strip out the console color control characters. I found a nice way to remove that, and you can see those commands on lines 113 and 115. One line is for appending to a file, and the other is for overwriting.


You can use ctee.sh like so:

unbuffer ansible-playbook playbook.yml | ctee.sh /var/log/ansible/playbook.$( date "+%Y-%m-%d-%H%M%S" ).log

Which will get your console the colorized output that helps for easy interpretation of the output, with the normal logging for later analysis.

Irfanview on Linux


Irfanview is a fantastic image viewer and batch utility for the Windows platform. But did you know that you can run Irfanview on GNU/Linux, and this post will show you how to do that. There is a caveat, though: Irfanview is not open source. It’s freeware. That might turn off some people, but I still choose to use it. It’s unparalleled in the GNU world.
There are several ways to get Irfanview on a GNU/Linux system, and they all use Wine.

Installing Irfanview with Winetricks

Winetricks is a fancy helper script that makes repetitive tasks in wine easier. It has an option built-in for installing Irfanview. It’s a piece of cake.
Make sure you have wine with your package manager.
dnf install wine
Then download winetricks from the link above and run the install irfanview command.
./winetricks -q irfanview
The -q is for unattended install. If you want to adjust the settings, run it without the -q.
Observe that winetricks mentions installing mfc42.dll for you. That is needed for the installer only.

Installing Irfanview with a custom-rolled package

You can choose to install Irfanview by assembling a package from the rpm spec and debian control scripts I’ve assembled at https://github.com/bgstack15/irfan.
git pull https://github.com/bgstack15/irfan
What is in the git repository is the source for just the packaging. The actual software source code is downloaded from official web sources upon building the rpm, and upon the installation of the dpkg file. As I said above, the software itself is freeware, so the source is not available for distribution.
A wrapper for rpmbuild and dpkg-deb is provided, as usr/share/irfan/inc/pack.
Run ./pack rpm or ./pack deb and the system will build you the type of package you specified, provided you have the rpm-build or dpkg-dev package.
For the rpm, you might need to generate some directories:
mkdir -p ~/rpmbuild/SOURCES ~/rpmbuild/SPECS ~/rpmbuild/RPMS ~/rpmbuild/BUILD ~/rpmbuild/BUILDROOT
In fact, you should run all this, which will download from github for you the package source.
mkdir -p ~/rpmbuild/SOURCES ~/rpmbuild/SPECS ~/rpmbuild/RPMS ~/rpmbuild/BUILD ~/rpmbuild/BUILDROOT
cd ~/rpmbuild/SOURCES
mkdir irfan-4.44-1; cd irfan-4.44-1
git init
git pull https://github.com/bgstack15/irfan
cd irfan-4.44-1
usr/share/irfan/inc/pack rpm

The generated rpm will appear in ~/rpmbuild/RPMS/noarch.
Then you can run dnf install ./irfan-4.44-1.noarch.rpm.

The benefits of rolling your own package

The package provided on github includes a menu shortcut to Irfanview, as well as mimetype defaults for jpg and png. You will be able to see Irfanview in the list of applications when you select a file in the file manager, right click, and select “Open with…” The winetricks option does not include that.


  1. Main irfanview site http://www.irfanview.info/
  2. http://www.boekhoff.info/?pid=linux&tip=install-irfan-view-on-linux
  3. Main wine site https://www.winehq.org/
  4. Latest winetricks script https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
  5. Irfan rpm and deb package source https://github.com/bgstack15/irfan

Nagios plugin to count apache threads


At work I have a misbehaving web server. Sometimes it spawns the maximum number of apache threads (which has a hardcoded maximum of 256, no matter what you configure) and then occupies 100% of the processor. I have decided that the normal nagios checks for the http site and ssh and so on aren’t good enough for monitoring purposes.

So I wrote my own simple nagios check. And then I put it in an rpm for easy deployment.

The nagios check

Here is the code for check_apache_threads, although you can check the latest version at my github page.

# File: /usr/lib64/nagios/plugins/check_apache_threads
# Author: bgstack15@gmail.com
# Startdate: 2017-01-09 15:53
# Title: Nagios Check for Apache Threads
# Purpose: For a troublesome dmz wordpress host
# Package: nagios-plugins-apache-threads
# History:
# Usage:
# In nagios/nconf, use this checkcommand check command line: $USER1$/check_by_ssh -H $HOSTADDRESS$ -C "$USER1$/check_apache_threads -w $ARG1$ -c $ARG2$"
# Reference: general design /usr/lib64/nagios/plugins/check_sensors
# general design http://www.kernel-panic.it/openbsd/nagios/nagios6.html
# case -w http://www.linuxquestions.org/questions/programming-9/ash-test-is-string-a-contained-in-string-b-671773/
# Improve:
PROGNAME=`basename $0`
PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'`
. $PROGPATH/utils.sh
print_usage() {
cat <<EOF
Usage: $PROGNAME -w <thresh_warn> -c <thresh_crit>
print_help() {
print_revision $PROGNAME $REVISION
echo ""
echo ""
echo "This plugin checks for the number of active apache threads."
echo ""
exit $STATE_OK
# Total httpd threads
tot_apache_threads="$( ps -ef | grep -ciE "httpd$" )"
while test -n "${1}";
case "$1" in
exit $STATE_OK
print_revision $PROGNAME $REVISION
exit $STATE_OK
-v | --verbose)
verbosity=$(( verbosity + 1 ))
-w | --warning | -c | --critical)
if [[ -z "$2" || "$2" = -* ]];
# Threshold not provided
echo "$PROGNAME: Option '$1' requires an argument."
elif [[ "$2" = +([0-9]) ]];
# Threshold is a number
# use for a percentage template, from reference 2
#elif [[ "$2" = +([0-9])% ]]; then
# # Threshold is a percentage
# thresh=$(( tot_mem * ${2%\%} / 100 ))
# Threshold is not a number or other valid input
echo "$PROGNAME: Threshold must be an integer."
case "$1" in *-w*) thresh_warn=$thresh;; *) thresh_crit=$thresh;; esac
shift 2
exit $STATE_OK
echo "$PROGNAME: Invalid option '$1'"
if test -z "$thresh_warn" || test -z "$thresh_crit";
# One or both values were unspecified
echo "$PROGNAME: Threshold not set"
elif test "$thresh_crit" -le "$thresh_warn";
echo "$PROGNAME: Critical value must be greater than warning value."
if test "$verbosity" -ge 2;
# Print debugging information
/bin/cat <<EOF
Debugging information:
Warning threshold: $thresh_warn
Critical threshold: $thresh_crit
Verbosity level: $verbosity
Apache threads: ${tot_apache_threads}
if test "${tot_apache_threads}" -gt "${thresh_crit}";
# too many apache threads
echo "APACHE CRITICAL - $tot_apache_threads"
elif test "${tot_apache_threads}" -gt "${thresh_warn}";
echo "APACHE WARNING - $tot_apache_threads"
# fine
echo "APACHE OK - $tot_apache_threads"
exit $STATE_OK

Walking through the code

I included the code above so it gets cached by web crawlers. You should look at the code on github so you get the proper indentations, and line numbers.

So the general format of this script I got from a local file, check_sensor, and Reference 1 below.

The utils.sh call provides nagios-related definitions, including the exit codes that you see used like $STATE_OK.

The shell script is pretty self-explanatory, really. The variables are initialized and the actual checked value is calculated (ps -ef | grep httpd). About half the script (lines 51-100) is parsing the parameters, which is a nice, simple solution if you have predictable and simplified input (like from nagios) and you don’t do the proper parameter parsing that includes -XvalueofXhere with no space between the flag and the value.

Some sanity checking for threshholds (102-113) and debugging information if given enough verbosity (115-125), and then the actual results are determined in 127-140.

Final thoughts

The hardest part of using this plugin is not writing, using, or deploying the shell script. The hardest part is getting the script to run. To use this check properly, you actually need to write a nagios checkcommand like so:
$USER1$/check_by_ssh -H $HOSTADDRESS$ -C "$USER1$/check_apache_threads -w $ARG1$ -c $ARG2$"
With the arguments as the numbers for your thresholds. I used the values 50 and 150 for warning and critical.

Any questions?



  1. General design http://www.kernel-panic.it/openbsd/nagios/nagios6.html
  2. case -w http://www.linuxquestions.org/questions/programming-9/ash-test-is-string-a-contained-in-string-b-671773/

Moving the application installation directory for bgscripts


My bgscripts package in version 1.1-27 and before was installed in /usr/bgscripts. The more I thought about it, and the more I read the spec for FHS 3.0 (filesystem hierarchy standard) (PDF), the more I realized it should actually be in /usr/share/bgscripts.

Moving the files in the build directory was easy.

Wrapper script

But despite my symlinks in /usr/bin, which were easy to update, I have many, many hard-coded pathname calls of my scripts everywhere. So to mitigate the problem, I wrote a fancy wrapper script for regular scripts, including bup, send, bgscripts.bashrc, rdp, and treesize.

I needed to send myself a message with the various information about what script called the old location. I picked send.sh because that’s what it’s for– sending emails. I slapped in a bunch of diagnostic information and wrote a call to the new location.

# Wrapper at legacy location for bgscripts. Sends alert and then continues the process.
while read flocation; do if test -x ${flocation} && test "$( ${flocation} --fcheck )" -ge 20161212; then frameworkscript="${flocation}"; break; fi; done <<EOFLOCATIONS
test -z "${frameworkscript}" && echo "$0: framework not found. Aborted." 1>&2 && exit 4
. ${frameworkscript} || echo "$0: framework did not run properly. Aborted." 1>&2
pwd="$( pwd )"
psout="$( ps -ef )"
parentprocess="$( ps -ef | grep -iE -- "${thisppid}" | grep -viE -- "grep.*-iE.*--" )"
/usr/share/bgscripts/send.sh -hs "bgscripts alert ${server}: ${scriptfile}" bgstack15@gmail.com <<EOF
----- Description -----
This alert means that script "${scriptfile}" was called, and you need to fix it because /usr/bgscripts/* has been deprecated and will be removed in a future version.
----- Debug info-----
pwd: ${pwd}
Scriptdir: ${scriptdir}
Scriptfile: ${scriptfile}
All parameters: $@
Server: ${server}
Now: ${now}
Thisos: ${thisos}
Thisflavor: ${thisflavor}
Thisppid: ${thisppid}
Parent process: ${parentprocess}
----- Process list -----
/usr/share/bgscripts/${scriptfile} "${@}"

So if something of mine calls /usr/bgscripts/bgscripts.bashrc, this wrapper script will throw an email alert, and then redirect the script call so workflows are not interrupted!

The very first production use of the wrapper script was when I logged onto my test Ubuntu box to conduct a deep-dive search (more on that in the next heading) of scripts that call framework.sh. I got an email right away, saying I had dot-sourced the bashrc script. Looking at the diagnostic info, I was reminded that I tended to hardcode into my ~/.bashrc the call to /usr/bgscripts/bgscripts.bashrc.

I have now updated that to point to /usr/bin/bp, so in the future it will point to wherever I want it to. However, I seriously doubt the location will change now. My package is now FHS 3.0 compliant, and I don’t want to break that.

Deep dive search

So, I wanted to conduct a deep-dive search of all shell scripts (defined by me as everything ending in .sh, because I almost always use the extension) on all systems that refer to framework.sh, which is going to be the big hangup. So I whipped up this oneliner.
sudo updatedb; locate .sh | grep -iE "\.sh$" | grep -viE "\/usr\/src|\/usr\/share|\/usr\/lib|\/home\/.*\/rpmbuild/|\/home\/work\/.*clean" | xargs grep -iE "framework\.sh"

Now, an reading of my code shows that many of my scripts do a lookup for framework.sh in various locations, including ./framework.sh, ~/framework.sh, /usr/local/bin/framework.sh, and so on. You can observe this pattern in my wrapper script in this post.

So the serach will catch those, but I will recognize those blocks of code because they are just the filename on a separate line (in a here-doc) and as long as I see the /usr/share/bgscripts/framework.sh final resting place of framework, I’ll be satisfied.



  1. Filesystem hierarchy standard 3.0 http://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
  2. FHS 3.0 in pdf http://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.pdf
  3. Here document https://en.wikipedia.org/wiki/Here_document

Grep odt file


In the GNU/Linux world, you spend a lot of time on the command line. Searching a text file is a piece of cake:
grep -iE "expression" file1

You might even use a gui, and inside that gui you might even use an open-source office suite for all those times that plain text isn’t enough. But what about when you want to search one of those odt files you vaguely remember is some form of xml?

Easy. You use unoconv or odt2txt (look those up in your package manager) and then grep the outputted file. Or you can use the –stdout option.

unoconv -f txt foo.odt

unoconv -f txt --stdout foo.odt | grep -iE "Joe Schmoe"


I first started tackling this problem by figuring out how to access the xml inside. I learned an odt file is zipped, but a tar xf didn’t help. Turns out it was some other compression, that unzip manages.

I also had to actually learn the tiniest bit of perl, as regular GNU grep (and I inferred sed) doesn’t do non-greedy wildcard matching.

So I got this super-complicated one-liner going before I decided to try a different approach and discovered the unoconv and odt2txt applications.

time unzip -p foo.odt content.xml | sed -e 's/\([^n]\)>\n(.*)<\/\1>/\2/;s/<text:h.*?>(.*)<\/text:h>/\1/;' -e 's/<style:(font-face|text-properties).*\/>//g;' | sed -e "s/'/\'/g;s/"/\"/g;s/<text:.*break\/>//g;"




  1. Unzipping an odt file https://ubuntuforums.org/showthread.php?t=899179&s=3aa7c303c4a5655e039600c4082d7a2c&p=5653494#post5653494
  2. Perl non-greedy wildcard matching http://stackoverflow.com/a/1103177/3569534