8

When I try to execute mail from inside a function in a bash script it creates something similar to a fork bomb. To clarify, this creates the issue:

#!/bin/bash

mail() {
    echo "Free of oxens" | mail -s "Do you want to play chicken with the void?" "[email protected]"
}

mail

exit 0

Sometimes you can just kill the command and it'll kill the child processes, but sometimes you'll have to killall -9.

It doesn't care whether the mail were sent or not. The fork bomb is created either way. And it doesn't seem as adding any check for the exit code, such as if ! [ "$?" = 0 ], helps.

But the script below works as intended, either it outputs an error or it sends the mail.

#!/bin/bash

echo "Free of oxens" | mail -s "Do you want to play chicken with the void?" "[email protected]"

exit 0

Why does this happen? And how would you go about checking the exit code of the mail command?

1
  • 10
    It is called recursion.
    – Jakuje
    Commented Jan 20, 2016 at 17:57

3 Answers 3

29

You're invoking the function mail from within the same function:

#!/bin/bash

mail() {
    # This actually calls the "mail" function
    # and not the "mail" executable
    echo "Free of oxens" | mail -s "Do you want to play chicken with the void?" "[email protected]"
}


mail

exit 0

This should work:

#!/bin/bash

mailfunc() {
    echo "Free of oxens" | mail -s "Do you want to play chicken with the void?" "[email protected]"
}

mailfunc

exit 0

Note that function name is no longer invoked from within the function itself.

1
  • 3
    Happens to the best of us, man.
    – Almo
    Commented Jan 20, 2016 at 20:55
15

Otherwise:

mail(){

    echo olly olly oxenfree | command mail -s 'and the rest' and@more
}

...should work fine.

3
  • 7
    Perhaps emphasising the command part, as for the layperson it is hard to notice that change along with the olly olly oxenfree and 'and the rest' and@more changes, especially with the syntax highlighting.
    – wizzwizz4
    Commented Jan 20, 2016 at 17:22
  • 1
    @wizzwizz4 - I support this comment.
    – mikeserv
    Commented Jan 20, 2016 at 17:33
  • 1
    It is funny though...
    – wizzwizz4
    Commented Jan 20, 2016 at 17:39
3

The most "traditional" solution in these cases is actually to call the command with full path:

mail() {
    echo "Free of oxens" | /usr/bin/mail -s "Do you want to play chicken with the void?" "[email protected]"
}

All other answers work, and are probably more portable, but I think that this is the most likely solution you'd find in scripts in the wild real world, so I'm including it for completeness.

3
  • 3
    Indeed I'm not used to mail being in /usr/bin.
    – Joshua
    Commented Jan 20, 2016 at 20:26
  • 3
    @Joshua, it seems to be there on OS X. In CentOS 6 it's /bin/mail. I think this proves the value of the command mail syntax.
    – Wildcard
    Commented Jan 20, 2016 at 20:49
  • Arch Linux also has this in /usr because their paradigm is to move all the binaries to the same directory, so /bin is just a symlink to /usr/bin. So yes... this isn't portable, but it's more commonly seen than command, somehow - especially in legacy boot scripts that were made specifically to each distribution, all the absolute paths were hardcoded (rc scripts in Slackware, for instance).
    – orion
    Commented Jan 21, 2016 at 12:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .