Why does dot sourcing of ksh functions behave so differently between AIX, Solaris, and Linux? How can I make Linux behave the way I want in the test I show below?
I have a library of interdependent functions I have developed and use in ksh in AIX. They also run in Solaris. Now I am migrating them to Linux. They aren't working properly in Linux. I have devised a test to illustrate the differences. I am looking for an explanation of the behavior, particularly in Linux, and how I can resolve it to be like Solaris (which would be OK) or like AIX (which would be ideal).
Test 1 below is the behavior I like. Test 2 is OK. Test 3 is the one I don't understand and need to fix.
I start by creating this file that contains the "MyFun" function definition in a directory that is on my PATH:
$ cat MyFun
#! /bin/ksh
print -- "In file MyFun, before def of function MyFun. PID=$$, system=$( uname -rsv )"
function MyFun
{
print -- "In function MyFun. PID=$$, system=$( uname -rsv )"
return $(( $# % 128 )) #number of arguments mod 128
}
print -- "In file MyFun, after def of function MyFun. PID=$$, system=$( uname -rsv )"
The contents above are stored in file "MyFun", which does NOT require execute permissions:
$ ls -l MyFun | xargs echo | cut -d ' ' -f 1,9
-rw-r--r-- MyFun
############
TEST 1: run in AIX
(first install MyFun from above into a directory in your PATH, then cd to that directory)
Here when the file is dot sourced a second time, NONE of it executes. The system is caching the dot-sourcing operation, so if this function is shared by several other functions that dot source it and all are used in a script, it only executes once.
The important thing is that the inner part of the function never executes when the file is dot sourced (the function itself doesn't get called during dot sourcing). In this case the behavior is like an import (not include) statement, and is the behavior I want:
$ #dot source the file first time
$ . MyFun
In file MyFun, before def of function MyFun. PID=8908866, system=AIX 3 5
In file MyFun, after def of function MyFun. PID=8908866, system=AIX 3 5
$ #call the function after dot sourcing
$ MyFun
In function MyFun. PID=8908866, system=AIX 3 5
$ #dot source the file a second time
$ . MyFun
#(there is no output from the command above).
############
TEST 2: run in Solaris (first install MyFun from above)
(first install MyFun from above into a directory in your PATH, then cd to that directory)
Here when the file is dot sourced a second time, the file executes again just like the first time. The system is re-executing the entire file each time it is dot sourced, so if this function is shared by several other functions that dot source it and all are used in a script, the file re-executes every time and the function itself is redundantly redefined each time.
The important thing is that the inner part of the function still never executes when the file is dot sourced (the function itself doesn't get called during dot sourcing). This behaves like an include (not import) statement, and is inefficient compared to test 1, but still works:
$ #dot source the file first time
$ . MyFun
In file MyFun, before def of function MyFun. PID=29760, system=SunOS 5.10 Generic_141444-09
In file MyFun, after def of function MyFun. PID=29760, system=SunOS 5.10 Generic_141444-09
$ #call the function after dot sourcing
$ MyFun
In function MyFun. PID=29760, system=SunOS 5.10 Generic_141444-09
$ #dot source the file a second time
$ . MyFun
In file MyFun, before def of function MyFun. PID=29760, system=SunOS 5.10 Generic_141444-09
In file MyFun, after def of function MyFun. PID=29760, system=SunOS 5.10 Generic_141444-09
############
TEST 3: run in Linux (first install MyFun from above into a directory in your PATH, then cd to that directory)
Here when the file is dot sourced a second time, the FUNCTION BODY executes even though I don't want to CALL it.
The problem here is that the inner part of the function executes when the file is dot sourced after the first time (the function itself gets called during subsequent dot sourcing operations). I do not understand this behavior and it is harmful:
$ #dot source the file first time
$ . MyFun
In file MyFun, before def of function MyFun. PID=37604, system=Linux 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011
In file MyFun, after def of function MyFun. PID=37604, system=Linux 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011
$ #call the function after dot sourcing
$ MyFun
In function MyFun. PID=37604, system=Linux 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011
$ #dot source the file a second time
$ . MyFun
In function MyFun. PID=37604, system=Linux 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011