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?

roxto
  • 708
  • 4
  • 12

3 Answers3

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.

Andrew Henle
  • 3,722
  • 14
  • 13
15

Otherwise:

mail(){

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

...should work fine.

mikeserv
  • 57,448
  • 9
  • 113
  • 229
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.

orion
  • 12,302
  • 2
  • 31
  • 41
  • 3
    Indeed I'm not used to mail being in /usr/bin. – Joshua Jan 20 '16 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 Jan 20 '16 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 Jan 21 '16 at 12:34