Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?" "example@example.org"
}

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?" "example@example.org"

exit 0

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

share|improve this question
10  
It is called recursion. – Jakuje Jan 20 at 17:57
up vote 28 down vote accepted

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?" "example@example.org"
}


mail

exit 0

This should work:

#!/bin/bash

mailfunc() {
    echo "Free of oxens" | mail -s "Do you want to play chicken with the void?" "example@example.org"
}

mailfunc

exit 0

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

share|improve this answer
13  
shit... Well that's a miss to be ashamed of, haha. Thanks! – roxto Jan 20 at 10:47
3  
Happens to the best of us, man. – Almo Jan 20 at 20:55

Otherwise:

mail(){

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

...should work fine.

share|improve this answer
6  
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 Jan 20 at 17:22
1  
@wizzwizz4 - I support this comment. – mikeserv Jan 20 at 17:33
    
It is funny though... – wizzwizz4 Jan 20 at 17:39

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?" "example@example.org"
}

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.

share|improve this answer
3  
Indeed I'm not used to mail being in /usr/bin. – Joshua Jan 20 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 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 at 12:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.