Getopts Tutorial

−Table of Contents

Small getopts tutorial

When you want to parse commandline arguments in a professional way, getopts is the tool of choice. Unlike its older brother getopt (note the missing s!), it’s a shell builtin command. The advantage is

you don’t need to hand your positional parameters through to an external program
getopts can easily set shell variables you can use for parsing (impossible for an external process!)
you don’t have to argue with several getopt implementations which had buggy concepts in the past (whitespaces, …)
getopts is defined in POSIX®
Some other methods to parse positional parameters (without getopt(s)) are described in: How to handle positional parameters.

Note that getopts is not able to parse GNU-style long options (–myoption) or XF86-style long options (-myoption)!

Description

It’s useful to know what we’re talking about here, so let’s see… Consider the following commandline:

mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt
All these are positional parameters, but you can divide them into some logical groups:
-x is an option, a flag, a switch: one character, indroduced by a dash (-)
-f is also an option, but this option has an additional argument (argument to the option -f): /etc/mybackup.conf. This argument is usually separated from its option (by a whitespace or any other splitting character) but that’s not a must, -f/etc/mybackup.conf is valid.
-r depends on the configuration. In this example, -r doesn’t take arguments, so it’s a standalone option, like -x
./foo.txt and ./bar.txt are remaining arguments without any option related. These often are used as mass-arguments (like for example the filenames you specify for cp(1)) or for arguments that don’t need an option to be recognized because of the intended behaviour of the program (like the filename argument you give your text-editor to open and display – why would one need an extra switch for that?). POSIX® calls them operands.
To give you an idea about why getopts is useful: The above commandline could also read like…

mybackup -xrf /etc/mybackup.conf ./foo.txt ./bar.txt
…which is very hard to parse by own code. getopts recognized all the common option formats.
The option flags can be upper- and lowercase characters, and of course digits. It may recognize other characters, but that’s not recommended (usability and maybe problems with special characters).

How it works

In general you need to call getopts several times. Each time it will use “the next” positional parameter (and a possible argument), if parsable, and provide it to you. getopts will not change the positional parameter set — if you want to shift it, you have to do it manually after processing:

shift $((OPTIND-1))
# now do something with $@
Since getopts will set an exit status of FALSE when there’s nothing left to parse, it’s easy to use it in a while-loop:

while getopts …; do

done
getopts will parse options and their possible arguments. It will stop parsing on the first non-option argument (a string that doesn’t begin with a hyphen (-) that isn’t an argument for any option infront of it). It will also stop parsing when it sees the — (double-hyphen), which means end of options.

Used variables

variable description
OPTIND Holds the index to the next argument to be processed. This is how getopts “remembers” its own status between invocations. Also usefull to shift the positional parameters after processing with getopts. OPTIND is initially set to 1, and needs to be re-set to 1 if you want to parse anything again with getopts
OPTARG This variable is set to any argument for an option found by getopts. It also contains the option flag of an unknown option.
OPTERR (Values 0 or 1) Indicates if Bash should display error messages generated by the getopts builtin. The value is initialized to 1 on every shell startup – so be sure to always set it to 0 if you don’t want to see annoying messages!
getopts also uses these variables for error reporting (they’re set to value-combinations which arent possible in normal operation).

Specify what you want

The base-syntax for getopts is:

getopts OPTSTRING VARNAME [ARGS…]
where:
OPTSTRING tells getopts which options to expect and where to expect arguments (see below)
VARNAME tells getopts which shell-variable to use for option reporting
ARGS tells getopts to parse these optional words instead of the positional parameters
The option-string

The option-string tells getopts which options to expect and which of them must have an argument. The syntax is very simple — every option character is simply named as is, this example-string would tell getopts to look for -f, -A and -x:

getopts fAx VARNAME
When you want getopts to expect an argument for an option, just place a : (colon) after the proper option flag. If you want -A to expect an argument (i.e. to become -A SOMETHING) just do:

getopts fA:x VARNAME
If the very first character of the option-string is a : (colon), which normally would be nonsense because there’s no option letter preceeding it, getopts switches to the mode “silent error reporting”. In productive scripts, this is usually what you want (handle errors yourself and don’t get disturbed by annoying messages).

Custom arguments to parse

The getopts utility parses the positional parameters of the current shell or function by default (which means it parses “$@”).

You can give your own set of arguments to the utility to parse. Whenever additional arguments are given after the VARNAME parameter, getopts doesn’t try to parse the positional parameters, but these given words.

This way, you are able to parse any option set you like, here for example from an array:

while getopts :f:h opt “${MY_OWN_SET[@]}”; do

done
A call to getopts without these additional arguments is equivalent to explicitly calling it with “$@”:

getopts … “$@”
Error Reporting

Regarding error-reporting, there are two modes getopts can run in:

verbose mode
silent mode
For productive scripts I recommend to use the silent mode, since everything looks more professional, when you don’t see annoying standard messages. Also it’s easier to handle, since the failure cases are indicated in an easier way.

Verbose Mode

invalid option VARNAME is set to ? (quersion-mark) and OPTARG is unset
required argument not found VARNAME is set to ? (quersion-mark), OPTARG is unset and an error message is printed
Silent Mode

invalid option VARNAME is set to ? (question-mark) and OPTARG is set to the (invalid) option character
required argument not found VARNAME is set to : (colon) and OPTARG contains the option-character in question
Using it

A first example

Enough said – action!

Let’s play with a very simple case: Only one option (-a) expected, without any arguments. Also we disable the verbose error handling by preceeding the whole option string with a colon (:):

#!/bin/bash

while getopts “:a” opt; do
case $opt in
a)
echo “-a was triggered!” >&2
;;
\?)
echo “Invalid option: -$OPTARG” >&2
;;
esac
done
I put that into a file named go_test.sh, which is the name you’ll see below in the examples.
Let’s do some tests:

Calling it without any arguments

$ ./go_test.sh
$
Nothing happened? Right. getopts didn’t see any valid or invalid options (letters preceeded by a dash), so it wasn’t triggered.
Calling it with non-option arguments

$ ./go_test.sh /etc/passwd
$
Again — nothing happened. The very same case: getopts didn’t see any valid or invalid options (letters preceeded by a dash), so it wasn’t triggered.
The arguments given to your script are of course accessible as $1 – ${N}.

Calling it with option-arguments

Now let’s trigger getopts: Provide options.

First, an invalid one:

$ ./go_test.sh -b
Invalid option: -b
$
As expected, getopts didn’t accept this option and acted like told above: It placed ? into $opt and the invalid option character (b) into $OPTARG. With our case statement, we were able to detect this.
Now, a valid one (-a):

$ ./go_test.sh -a
-a was triggered!
$
You see, the detection works perfectly. The a was put into the variable $opt for our case statement.
Of course it’s possible to mix valid and invalid options when calling:

$ ./go_test.sh -a -x -b -c
-a was triggered!
Invalid option: -x
Invalid option: -b
Invalid option: -c
$
Finally, it’s of course possible, to give our option multiple times:

$ ./go_test.sh -a -a -a -a
-a was triggered!
-a was triggered!
-a was triggered!
-a was triggered!
$
The last examples lead us to some points you may consider:

invalid options don’t stop the processing: If you want to stop the script, you have to do it yourself (exit in the right place)
multiple identical options are possible: If you want to disallow these, you have to check manually (e.g. by setting a variable or so)
An option with argument

Let’s extend our example from above. Just a little bit:

-a now takes an argument
on an error, the parsing exits with exit 1
#!/bin/bash

while getopts “:a:” opt; do
case $opt in
a)
echo “-a was triggered, Parameter: $OPTARG” >&2
;;
\?)
echo “Invalid option: -$OPTARG” >&2
exit 1
;;
:)
echo “Option -$OPTARG requires an argument.” >&2
exit 1
;;
esac
done
Let’s do the very same tests we did in the last example:

Calling it without any arguments

$ ./go_test.sh
$
As above, nothing happend. It wasn’t triggered.
Calling it with non-option arguments

$ ./go_test.sh /etc/passwd
$
The very same case: It wasn’t triggered.
Calling it with option-arguments

Invalid option:

$ ./go_test.sh -b
Invalid option: -b
$
As expected, as above, getopts didn’t accept this option and acted like programmed.
Valid option, but without the mandatory argument:

$ ./go_test.sh -a
Option -a requires an argument.
$
The option was okay, but there is an argument missing.
Let’s provide the argument:

$ ./go_test.sh -a /etc/passwd
-a was triggered, Parameter: /etc/passwd
$
See also

http://wiki.bash-hackers.org/howto/getopts_tutorial

How do I get it so that with no arguments passed, it returns text saying “no arguments password, nothing triggered”?

I’d do it by checking $# before the while/getopts loop, if applicable:

if (($# == 0)); then

fi
If you really need to check if getopts found something to process you could make up a variable for that check:

options_found=0

while getopts “:xyz” opt; do
options_found=1

done

if ((!options_found)); then
echo “no options found”
fi

Another method of checking whether it found anything at all is to run a separate if statement right before the while getopts call.

if ( ! getopts “abc:deh” opt); then
echo “Usage: `basename $0` options (-ab) (-c value) (-d) (-e) -h for help”;
exit $E_OPTERROR;
fi

while etopts “abc:deh” opt; do
case $opt in
a) do something;;
b) do another;;
c) var=$OPTARG;;

esac
done

try this trick. When you discover that OPTARG von -c is something beginning with a hyphen, then reset OPTIND and re-run getopts (continue the while loop).

The code is relatively small, but I hope you get the idea.

Oh, of course, this isn’t perfect and needs some more robustness. It’s just an example.

#!/bin/bash

while getopts :abc: opt; do
case $opt in
a)
echo “option a”
;;
b)
echo “option b”
;;
c)
echo “option c”

if [[ $OPTARG = -* ]]; then
((OPTIND–))
continue
fi

echo “(c) argument $OPTARG”
;;
\?)
echo “WTF!”
exit 1
;;
esac
done

Stuff I Can Never Remeber

To exit a vterm use ~.

On Cisco use Ctrl-Shift-6… I think

Adding disks to VIO server config:

oem_setup_env

lspv > /tmp/disk_config_pre_change
chmod 777 /tmp/disk_config_pre_change
inq >> /tmp/disk_config_pre_change

exit
lsmap -all >> /tmp/disk_config_pre_change

chdev -l hdiskxx -a algorithm=round_robin -a reserve_policy=no_reserve

mkvdev –vdev -vadapter vhost -dev
e.g.
mkvdev –vdev hdisk14 –vadapter vhost17 -dev lparname_rootvg_disk1

Adding vpaths to server without running cfgmgr for whole box:
run:
cfgmgr -l fscsi0
cfgmgr -l fscsi1

cfallvpath

Analysing dumps:
hfd-wm-cov-db-02:/var/adm/ras >sysdumpdev -L
0453-039

Device name: /dev/lg_dumplv
Major device number: 10
Minor device number: 11
Size: 474104832 bytes
Uncompressed Size: 2415139298 bytes
Date/Time: Fri 3 Sep 16:51:22 2010
Dump status: 0
Type of dump: traditional
dump completed successfully

hfd-wm-cov-db-02:/ >kdb /dev/lg_dumplv
/dev/lg_dumplv mapped from @ 700000000000000 to @ 700000040000000
Preserving 1799410 bytes of symbol table [/unix]
The dump is compressed. Run the following command:
dd if=/dev/lg_dumplv bs=512 skip=1 count=925987 > dumpfile.BZ; dmpuncompress dumpfile.BZ
925987+0 records in.
925987+0 records out.
— replaced with dumpfile

kdb ./dumpfile /unix

stat

stat
Shows the system status and messages.
p (alias: proc) [*/slot/symb/eaddr]
Displays the process table.
u (alias: user) [-?][slot/symb/eaddr]
Displays u_area.
th (alias: thread) [*/slot/symb/eaddr/-w ?]
Displays the thread table.
mst [slot] [[-a] symb/eaddr]
Displays the mstsave area for the specified thread.
f (alias: stack) [+x/-x][th {slot/eaddr}]
Displays all stack frames for specified thread.
h (alias: ?) [topic]
Lists all subcommands.
Provides information about subcommands of kdb.
errpt
Displays error log messages.

Install Desktop Environment On CentOS 6.5 Minimal

After performing a base install of CentOS 6.5 using the minimal install CD, do the following to install a basic GNOME desktop environment:

# yum groupinstall "Desktop" "Desktop Platform" "X Window System" "Fonts"

Run the following on a particular package group in order to see detailed information including a description and which packages it will install.

# yum groupinfo groupname

There are additional package groups if you want something more than a basic desktop environment. For example,

# yum -y groupinstall "General Purpose Desktop"

To see a list of all the installed and available package groups:

# yum grouplist

Once installed, you can start GNOME by running:

$ startx

or

$ /sbin/telinit 5

To have CentOS boot into runlevel 5 “X11″ instead of runlevel 3 “Full multiuser mode”, modify the /etc/inittab file to change start up level from

id:3:initdefault:

to

id:5:initdefault:

My System Configuration

  • CentOS 6.5 x86 64-bit

References

Simplest Way To Rip A DVD To An ISO

dd if=/dev/dvd of=mynew.iso bs=2048


Now you can mount the iso as if it were an actual DVD or CD:

# mount -o ro,loop -t iso9660 mynew.iso /mnt/iso

This assumes that you have the mount point /mnt/iso already created.

Also if you were going to modify the image somehow you might want to leave off the ‘ro’ option.

If you want to make an ISO image of files or a directory that have long filenames then do something like this:

# mkisofs -o mynew.iso -J [files or directory]

Determine what device your CD/DVD burner is

The device is not always going to be /dev/cdrom or /dev/dvd or whatever. To determine what device you have do this:

# dmesg | grep ROM

The output looks something like this:

[    1.625249] ata1.00: ATAPI: TEAC DVD-ROM DV28EV, R.AB, max UDMA/33
[    1.657106] scsi 0:0:0:0: CD-ROM            TEAC     DVD-ROM DV28EV   R.AB PQ: 0 ANSI: 5
[    1.672009] Uniform CD-ROM driver Revision: 3.20
[    1.672165] sr 0:0:0:0: Attached scsi CD-ROM sr0
[ 8795.604839] scsi 4:0:0:0: CD-ROM            Memorex  MRX-650LE v1     9M62 PQ: 0 ANSI: 0
[ 8795.756728] sr 4:0:0:0: Attached scsi CD-ROM sr1

So I have a Teac CD-ROM at scsi id 0:0:0:0 as /dev/sr0
and a Memorex at scsi id 4:0:0:0 as /dev/sr1
So if I want to burn a DVD to the Memorex Burner I use /dev/sr1

Burning ISO images to DVD

Now if you want to create an actual DVD:

# growisofs -dvd-compat -Z /dev/dvd=mynew.iso

or

# growisofs -dvd-compat -Z /dev/[device]=mynew.iso

Or use whatever device the DVD writer shows up as.

Verify the burned DVD’s md5sum

To verify the burning to DVD:

# dd if=/dev/[device] | head -c `stat --format=%s mynew.iso` | md5sum

The resulting number you get should match the md5sum of the iso image.

Burning ISO images to CD

You need to determine the SCSI address of the CD burner. As root, issue the command:

# cdrecord --scanbus

In my case the CD Burner is on 2,0,0:

Cdrecord-Clone 2.01 (cpu-pc-linux-gnu) Copyright (C) 1995-2004 J�rg Schilling
Note: This version is an unofficial (modified) version with DVD support
Note: and therefore may have bugs that are not present in the original.
Note: Please send bug reports or support requests to http://bugzilla.redhat.com/bugzilla
Note: The author of cdrecord should not be bothered with problems in this version.
Linux sg driver version: 3.5.27
Using libscg version 'schily-0.8'.
cdrecord: Warning: using inofficial libscg transport code version (schily - Red Hat-scsi-linux-sg.c-1.83-RH '@(#)scsi-linux-sg.c      1.83 04/05/20 Copyright 1997 J. Schilling').
scsibus2:
        2,0,0   200) 'TSSTcorp' 'DVD+-RW TS-L632H' 'D400' Removable CD-ROM
        2,1,0   201) *
        2,2,0   202) *
        2,3,0   203) *
        2,4,0   204) *
        2,5,0   205) *
        2,6,0   206) *
        2,7,0   207) *

Then to burn the CD do:

# cdrecord --dev=2,0,0 name.iso

To erase a re-writable CD before burning do:

# cdrecord --dev=2,0,0 --blank=fast

Static Routing in Red Hat

Adding a route in Red Hat

It’s a wee bit different from AIX, where you can just add the route with:

# route add so.ur.ce.ip de.st.ip.ad

Under Red Hat you need to define static routing using route command. The configuration is stored under /etc/sysconfig/network-scripts/route-eth0 for eth0 interface.

Update route using route command

Type the following command:
# route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.8.2.65 eth0
# route -n

 

 

Create static routing file

The drawback of abive ‘route’ command is that, when RHEL reboots it will forget static routes. So store them in configuration file:
echo '10.0.0.0/8 via 10.8.2.65' >> /etc/sysconfig/network-scripts/route-eth0
Restart networking:
# service network restart
Verify new changes:
# route -n
# ping 10.8.2.65
# ping 10.8.2.10
# ping google.com
# traceroute google.com
# traceroute 10.8.2.10

Further readings:

  • man pages ip, route command

Tracing AIX Disks To VIO Server Mappings

This post is a list of the steps taken to map virtual SCSI disks back to the VIO servers on an AIX system. I had to carry out this process recently and decided to write up the steps for future reference.  Hopefully this can be of some help.

Requirements:

All scripts are run from NIM server and with keys exchanged between lpars, VIO servers and HMCs. SAN disks are allocated to VIO servers and are mapped to LPARs from VIOS.

http://www.ibm.com/developerworks/aix/library/au-aix-vioserver-v2/vir_scsi.gif

I recently had to document the mappings for a number of LPARs, documenting which disks led to which SAN LUNs on the respective VIO servers and found there was still no easy way to do this from the LPAR itself, so had to come up with a process to do so.

Step 1 – gather information from LPAR

First step is to gather info from AIX server which we would like to map back to the VIO. this can be done in a number of ways, but we will use lsdev -Cc disk to check for Virtual SCSI disks, then the lspath command to trace slot numbers back to the VIO. Once we determine that hdisk0 is served by our vio server, we could just use lscfg -l hdisk0 to find the local slot number, however this is a dual vio environment and it is necessary to check that the slot numbers are the same on each vio server. Hence we will use lspath -F “name,status,parent,connection” -l hdisk0 to give full mapping info to both VIO servers.

# lspath -F "name,status,parent,connection" -l hdisk0
hdisk0,Enabled,vscsi0,810000000000
hdisk0,Enabled,vscsi1,810000000000

From this output, we can see that there are two paths to this disk, through vscsi0 and vscsi1. Each vscsi device maps to a vhost device on a VIO server. As this is a dual VIO server configuration, we can assume that each path is a vhost device on a separate VIO server. Also, each path has the same LUN number of “810000000000”, suggesting that both VIO server are in sync and have the same vhost mapping. As each vhost / vscsi device can map multiple LUNs, each client LUN has an id beginning at “810000000000”, then “820000000000”, 83xxx and so on.

So, now we need the  client slot number for each device. Again there are multiple ways of doing this, including lscfg -l vscsix, however it’s neater to use lsslot -c slot to find everything we need:

# lsslot -c slot
# Slot                    Description       Device(s)
...
U8205.E6C.0123ABC-V12-C4  Virtual I/O Slot  vscsi0
U8205.E6C.0123ABC-V12-C5  Virtual I/O Slot  vscsi1

From here, we can see that the LPAR ID is represented by V12 and the client slots are C4 and C5 repectively. Cool, now we need the info from the HMC to get the server slots. Unfortunately, this is a bit of a faff and we need to log into the HMC to trace this back. I will provide a script to automate this process, however it’s important that we understand the steps involved before we can do so.

This can be done from the GUI, but for speed, we will go to the command line. So, from the HMC command line you need to type the following:

-> lssyscfg -r sys -F "name" | grep 0123ABC 
U8205-E6C-0123ABC-> lshwres -r virtualio --rsubtype scsi -m U8205-E6C-0123ABC --filter lpar_ids=12 -F "slot_num,remote_slot_num,remote_lpar_name"
5,24,vio33b
4,24,vio33a

See here for more on command line basics.

However, this is easier done from the NIM server if you have your ssh keys set up. See here, for more info on setting or resetting your ssh keys on NIM.

nim01 # ssh -q hscroot@hmc1 lssyscfg -r sys -F "name" | grep 0123ABC
U8205-E6C-0123ABC

nim01 # ssh -q hscroot@hmc1 lshwres -r virtualio --rsubtype scsi -m U8205-E6C-0123ABC --filter lpar_ids=12 -F "slot_num,remote_slot_num,remote_lpar_name"
5,24,vio33b
4,24,vio33a

Obviously replace hscroot@hmc1 with your username@hmcname and -m <systemname> with your system name.

Now to gather the info from the VIO server. You can do this by logging into the VIOS as padmin and typing lsmap -all |more and search through till you find your slot number from before (24 in our case).

SVSA            Physloc                                      Client Partition ID
--------------- -------------------------------------------- ------------------
vhost14         U8205.E6C.0123ABC-V1-C24                     0x0000000c

VTD                   vtscsi01
Status                Available
LUN                   0x8100000000000000
Backing device        hdiskpower01
Physloc               U78AA.001.XDHJSJD-P1-C2-T1-L73
Mirrored              false

VTD                   vtscsi01
Status                Available
LUN                   0x8200000000000000
Backing device        hdiskpower02
Physloc               U78AA.001.XDHJSJD-P1-C2-T1-L73
Mirrored              false

From here we can see that the vhost device at slot 24 (vhost14) is holding a number of disks. We can identify the disk we looked up from earlier by refering to the LUN ID of 810000000000. We know this is hdisk0 from the LPAR information.

Now see that the backing device for this is hdiskpower01. This is because I’m using EMCPower software for my MPIO. This value may read hdiskX in your case. If so, you won’t need to follow the steps required for mapping the EMCPower disks.

So, from this information, we can run an lspv on the VIO server to find the physical disk

vio33a # lspv | grep hdiskpower1
hdiskpower1          00f7e02exxxx1111                    rootvg          active

Of course if the pvid was set up correctly (by installing with: chdev -l hdiskpower01 -a pvid=yes), then we could possibly just take the pvid of each disk from the LPAR and grep for that same pvid on the VIO server.

lpar1 # lspv | grep hdisk0
hdisk0          00f7e02exxxx1111                    rootvg          active
padmin@vio33a $ lspv |grep 00f7e02exxxx1111                    
hdiskpower1     00f7e02exxxx1111                    None

However, this is not always reliable if these steps were not followed correctly during setup, so we will continue with this, more robust method.

So now we have the hdiskpower device on the VIO server. If we want to find the actual SAN LUNs which were mapped via EMCPower Path, we need to execute the following command:

root@vio33a # powermt display dev=all |grep -p hdiskpower1$
Pseudo name=hdiskpower1
Symmetrix ID=000123456789
Logical device ID=1ABC
state=alive; policy=SymmOpt; priority=0; queued-IOs=0;
==============================================================================
--------------- Host ---------------   - Stor -   -- I/O Path --  -- Stats ---
###  HW Path               I/O Paths    Interf.   Mode    State   Q-IOs Errors
==============================================================================
   0 fscsi0                   hdisk3    FB  8fA   active  alive       0      0
   1 fscsi1                   hdisk7    FB  9fB   active  alive       0      0

So now we finsally have a mapping of the LUN ID, 1ABC and the low level disks used on the VIO server from the SAN software. Now we need to do that for the second VIO server and alll the other disks, while we’re at it!

Pain the neck?

Indeed, so we need a way of automating this process. I’ve adapted a small perl script to suite my needs. As previously stated, all command are run from my NIM server, which has passwordless ssh access to all lpars and the HMCs. From here, we can gather all the information we want and blat it out to a file.

Handy Sed One Liners

Remove all whitespaces from the beginning of a line:
:%s/^\s\+

Delete all trailing whitespace (at the end of each line) with:

:%s/\s\+$//

Tidy up ugly HTML files to be spaced like a normal person:

vim fileIn.html -c "set sw=2 | %s/>/>\r/ | execute 'normal gg=G' | set nohlsearch | g/^\\s*\$/d"

Set up SSH Tunnel

If you don’t have firewall access to a specific server on a subnet, you can use ssh tunnelling to forward requests from an existing host.

Find a server you do have access to and create the ssh tunnel as below, where destinationhost is the server you ultimately want to access and jumphost is the server you have access to:

destinationhost# ssh -L22033:localhost:22033 -R22033:10.220.112.173:670 -N jumphost

jumphost# ssh -p22033 userid@localhost

You may need to add a hostfile entry for jumphost

Creating a Subsystem in AIX

Want a deamon to be controlled by the system resource controller?

Easy:

Create fksubsys service:

mkssys -p /path/to/fkcmd \ # Absolute path to subsystem bin or script
-a “arg1 arg2″ \     # if Arguments to the command
-s fksubsys \        # Unique name for the subsystem (-t fkalias)
-G fkgrp \           # Subsys group
-u 202 \             # User id for the subsystem (0 for root)
-i /dev/console \    # Stdin got from (default)
-o /dev/console \    # Stdout sent to (default)
-e /dev/console \    # Stderr sent to (default)
-R \                 # Restart subsys if halted abnormally (or -O)
-Q \                 # One instance only # -q if multiple instances
-S \                 # Subsys supports signals
\                   # or -I msgqueue -m msgtype (or -K if sockets)
-f 9 \               # signal KILL for forced stopsrc -f
-n 15 \              # signal TERM for normal stopsrc
-w 10 \              # 10 seconds between a TERM and KILL & restart)
-E 24 \              # Subsys priority (20 default)
-d                   # lssrc -a lists subsys even if inactive else -D

lssrc -S -s fksubsys # Check the service’s configuration: OR…
odmget -q subsysname=fksubsys SRCsubsys # … via the odm.

startsrc -s fksubsys  # startsrc -g fkgrp  # two ways to launch it
stopsrc -s fksubsys # and to stop it

mkitab -i cron fkcmd:2:respawn:startsrc -s fksubsys # start subsys via /etc/inittab