This site is currently read-only as we are migrating to Oracle Forums for an improved community experience. You will not be able to initiate activity until January 31st, when you will be able to use this site as normal.

    Forum Stats

  • 3,890,387 Users
  • 2,269,776 Discussions
  • 7,916,824 Comments

Discussions

Why a recursive script has trouble calling itself?

Tater_Salad
Tater_Salad Member Posts: 90 Red Ribbon
edited Apr 27, 2018 10:30AM in Generic Linux

Hi,

I have this simple rescursive script.

#!/bin/ksh#PS4='+$(date "+%F %T") ${FUNCNAME[0]}() $BASH_SOURCE:${BASH_LINENO[0]}+ 'set -o xtrace    # Comment this line to disable tracing.if [ -z $count ]   then      count=0fithis_dir=`pwd`if [ $count < 10 ]   then     ((count++))     echo 'count '$count     ${this_dir}/$0   fiecho "Out of it!"exit 0

As you can see I'm having it traced in the commands up-top.

I'm getting the following traced output:

[email protected] $ ./reroute.ksh +2018-04-26 09:47:26 () :+ [ -z ]+2018-04-26 09:47:26 () :+ count=0+2018-04-26 09:47:26 () :+ pwd+2018-04-26 09:47:26 () :+ this_dir=/home/c037024+2018-04-26 09:47:26 () :+ [ 0 ]+2018-04-26 09:47:26 () :+ ./reroute.ksh[13]: 10: cannot open [No such file or directory]+2018-04-26 09:47:26 () :+ echo 'Out of it!'Out of it!+2018-04-26 09:47:26 () :+ exit [email protected] $ 

Why does it not recognize the script I'm trying to call?

Tagged:
Tater_Salad

Best Answer

  • Dude!
    Dude! [email protected]Member Posts: 22,830 Black Diamond
    edited Apr 26, 2018 12:54PM Answer ✓

    If you you execute ./reroute.ksh then $0 will be ./reroute.ksh

    this_dir=/home/c037024 and ${this_dir}/$0 will essentially execute the following:

    /home/c037024/./reroute.ksh

    That of course won't work.

    However, the logic of your procedure is bad. The way I see it, you are creating an infinite loop. Not only will executing the program again not know about "count", but you are also continuously resetting it to 0. Making a program call itself will still load the stack with whatever remains in the initial procedure. Making a program call itself is always a bad idea. I suggest you create a function, rather than having the program call itself.

Answers

  • Nik
    Nik Blocked Member Posts: 2,879 Bronze Crown
    edited Apr 26, 2018 12:31PM

    Hi.

    Change line 13    if [ $count < 10 ]    to

    if (( $count < 10 ))

    or

    if [ $count -lt 10 ]  

    Also you must export variable count. Or you  got fork bomb.

    Change   count=0  to

     export  count=0 

    Regards,

    Nik

  • Dude!
    Dude! [email protected]Member Posts: 22,830 Black Diamond
    edited Apr 26, 2018 12:54PM Answer ✓

    If you you execute ./reroute.ksh then $0 will be ./reroute.ksh

    this_dir=/home/c037024 and ${this_dir}/$0 will essentially execute the following:

    /home/c037024/./reroute.ksh

    That of course won't work.

    However, the logic of your procedure is bad. The way I see it, you are creating an infinite loop. Not only will executing the program again not know about "count", but you are also continuously resetting it to 0. Making a program call itself will still load the stack with whatever remains in the initial procedure. Making a program call itself is always a bad idea. I suggest you create a function, rather than having the program call itself.

  • Dude!
    Dude! [email protected]Member Posts: 22,830 Black Diamond
    edited Apr 26, 2018 1:29PM

    Why ksh? Ksh under Linux is not the same as good old ksh on Unix systems. Pdksh is no longer available, at least not for current OS distributions. I could not think of any good reason to use ksh over bash. Linux uses bash. You are increasing the odds using ksh and Linux admins may not be able to help you with ksh specifics.

  • Tater_Salad
    Tater_Salad Member Posts: 90 Red Ribbon
    edited Apr 26, 2018 2:43PM

    Yup! There it is! I was literally board at work this morning so I started playing with recursion. This simple script illustrates it pretty well for the unindoctrinated from beggining to end.

    First, the corrected script.

    [email protected] $ cat reroute.ksh#!/bin/ksh#PS4='+$(date "+%F %T") ${FUNCNAME[0]}() $BASH_SOURCE:${BASH_LINENO[0]}+ 'set -o xtrace    # Comment this line to disable tracing.  if [ -z $count ]   then     export  count=0fi if [ $count -lt 10 ]    then     ((count++))     echo "count "$count     ./$0   fiecho "Out of it!"echo "count back! "$countexit 0

    And, of course, the output.

    [email protected] $ ./reroute.ksh +2018-04-26 13:36:02 () :+ [ -z ]+2018-04-26 13:36:02 () :+ count=0+2018-04-26 13:36:02 () :+ export count+2018-04-26 13:36:02 () :+ [ 0 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 1'count 1+2018-04-26 13:36:02 () :+ ././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 1 ]+2018-04-26 13:36:02 () :+ [ 1 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 2'count 2+2018-04-26 13:36:02 () :+ ./././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 2 ]+2018-04-26 13:36:02 () :+ [ 2 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 3'count 3+2018-04-26 13:36:02 () :+ ././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 3 ]+2018-04-26 13:36:02 () :+ [ 3 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 4'count 4+2018-04-26 13:36:02 () :+ ./././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 4 ]+2018-04-26 13:36:02 () :+ [ 4 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 5'count 5+2018-04-26 13:36:02 () :+ ././././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 5 ]+2018-04-26 13:36:02 () :+ [ 5 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 6'count 6+2018-04-26 13:36:02 () :+ ./././././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 6 ]+2018-04-26 13:36:02 () :+ [ 6 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 7'count 7+2018-04-26 13:36:02 () :+ ././././././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 7 ]+2018-04-26 13:36:02 () :+ [ 7 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 8'count 8+2018-04-26 13:36:02 () :+ ./././././././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 8 ]+2018-04-26 13:36:02 () :+ [ 8 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 9'count 9+2018-04-26 13:36:02 () :+ ././././././././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 9 ]+2018-04-26 13:36:02 () :+ [ 9 -lt 10 ]+2018-04-26 13:36:02 () :+ ((count++))+2018-04-26 13:36:02 () :+ echo 'count 10'count 10+2018-04-26 13:36:02 () :+ ./././././././././././reroute.ksh+2018-04-26 13:36:02 () :+ [ -z 10 ]+2018-04-26 13:36:02 () :+ [ 10 -lt 10 ]+2018-04-26 13:36:02 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:02 () :+ echo 'count back! 10'count back! 10+2018-04-26 13:36:02 () :+ exit 0+2018-04-26 13:36:02 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:02 () :+ echo 'count back! 10'count back! 10+2018-04-26 13:36:02 () :+ exit 0+2018-04-26 13:36:02 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:02 () :+ echo 'count back! 9'count back! 9+2018-04-26 13:36:02 () :+ exit 0+2018-04-26 13:36:02 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:02 () :+ echo 'count back! 8'count back! 8+2018-04-26 13:36:02 () :+ exit 0+2018-04-26 13:36:02 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:02 () :+ echo 'count back! 7'count back! 7+2018-04-26 13:36:02 () :+ exit 0+2018-04-26 13:36:02 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:02 () :+ echo 'count back! 6'count back! 6+2018-04-26 13:36:03 () :+ exit 0+2018-04-26 13:36:03 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:03 () :+ echo 'count back! 5'count back! 5+2018-04-26 13:36:03 () :+ exit 0+2018-04-26 13:36:03 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:03 () :+ echo 'count back! 4'count back! 4+2018-04-26 13:36:03 () :+ exit 0+2018-04-26 13:36:03 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:03 () :+ echo 'count back! 3'count back! 3+2018-04-26 13:36:03 () :+ exit 0+2018-04-26 13:36:03 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:03 () :+ echo 'count back! 2'count back! 2+2018-04-26 13:36:03 () :+ exit 0+2018-04-26 13:36:03 () :+ echo 'Out of it!'Out of it!+2018-04-26 13:36:03 () :+ echo 'count back! 1'count back! 1+2018-04-26 13:36:03 () :+ exit 0
  • Nik
    Nik Blocked Member Posts: 2,879 Bronze Crown
    edited Apr 26, 2018 3:23PM

    Hi.

    You can not change line   ${this_dir}/$0 

    You script will work with this line.

    Correct line:

    $0

    With ./$0 - you see that  path increasing ./././././././././././reroute.ksh 

    With current and old setting - you script will not work in case you run it with absolute path.

    /home/c037024/reroute.ksh

    Regards,

      Nik

  • Dude!
    Dude! [email protected]Member Posts: 22,830 Black Diamond
    edited Apr 26, 2018 3:48PM

    One reason to like bash:

    $ /home/oracle/aa

    /home/oracle/aa

    aa

    $ cat aa

    #/bin/bash

    echo $0

    echo ${0##*/}

    Tater_Salad
  • Tater_Salad
    Tater_Salad Member Posts: 90 Red Ribbon
    edited Apr 26, 2018 5:27PM
    With ./$0 - you see that  path increasing ./././././././././././reroute.ksh 

    Yeah, I kind of like that it does that. It's like it's literally illustrating what happens during recursion. With every "re"- call you add another "nested" level.

  • Tater_Salad
    Tater_Salad Member Posts: 90 Red Ribbon
    edited Apr 27, 2018 10:30AM

    You know what "Dude!"? That's good advice. I've just been initializing my script with #!/bin/ksh for so long it just became kind of a habit. I'm going to start using #!/bin/bash from now on just like you said, NOT "to increase your odds" of having an issue caused by the shell.

    A minor point, but a good one!

    Thanks Bud!

    Tater

This discussion has been closed.