Can you execute a Bash function with the `at` command?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












5















I want to execute a Bash function at a scheduled time. I think the right tool for this is the at command.



However, it doesn't seem to be working.



function stupid () 
date


export -f stupid

cat << EOM | at now + 1 minute
stupid
EOM


After waiting the minute, I check my mail and this is the error I see:



sh: line 41: syntax error near unexpected token `=() date"
"'
sh: line 41: `"}; export BASH_FUNC_stupid()'


I don't understand what's going wrong here, especially since I know the function works.



$ stupid
Fri May 29 21:05:38 UTC 2015


Looking at the error, I think the incorrect shell is being used to execute the function (sh as opposed to bash), but if I check $SHELL I see it points to /bin/bash, and the man page for at says:



$ echo $SHELL
/bin/bash
$ man at

...

SHELL The value of the SHELL environment variable at the time
of at invocation will determine which shell is used to
execute the at job commands.


So Bash should be the shell running my function.



What going on here? Is there a way to get my Bash function to run with at?










share|improve this question



















  • 1





    lists.gnu.org/archive/html/bug-bash/2014-09/msg00251.html

    – llua
    May 29 '15 at 21:56











  • @llua - Great find. I think I am running into the same issue, which is apparently a problem with Bash. Here's a similar report on the Red Hat bug tracker (linked to from that thread). For the record, I am running GNU bash, version 4.1.2(1)-release, which predates the shellshock fixes discussed in that thread by a few years. So perhaps it's not exactly the same issue. I should try with the latest release of Bash to see if this has been fixed.

    – Nick Chammas
    May 29 '15 at 22:22











  • Wow, this is weird. If I upgrade to the latest (I think) release, 4.3.30(1)-release and try the original snippet from my question, I now get: /bin/bash: line 1: stupid: command not found. So now it looks like bash and not sh is running, which is good, but the function is no longer accessible.

    – Nick Chammas
    May 29 '15 at 22:49











  • Even weirder on Bash 4.3.30: If I submit bash -c 'stupid' to at instead of just stupid, I get the original syntax error message with sh:. I'm lost now. ¯_(ツ)_/¯

    – Nick Chammas
    May 29 '15 at 22:51















5















I want to execute a Bash function at a scheduled time. I think the right tool for this is the at command.



However, it doesn't seem to be working.



function stupid () 
date


export -f stupid

cat << EOM | at now + 1 minute
stupid
EOM


After waiting the minute, I check my mail and this is the error I see:



sh: line 41: syntax error near unexpected token `=() date"
"'
sh: line 41: `"}; export BASH_FUNC_stupid()'


I don't understand what's going wrong here, especially since I know the function works.



$ stupid
Fri May 29 21:05:38 UTC 2015


Looking at the error, I think the incorrect shell is being used to execute the function (sh as opposed to bash), but if I check $SHELL I see it points to /bin/bash, and the man page for at says:



$ echo $SHELL
/bin/bash
$ man at

...

SHELL The value of the SHELL environment variable at the time
of at invocation will determine which shell is used to
execute the at job commands.


So Bash should be the shell running my function.



What going on here? Is there a way to get my Bash function to run with at?










share|improve this question



















  • 1





    lists.gnu.org/archive/html/bug-bash/2014-09/msg00251.html

    – llua
    May 29 '15 at 21:56











  • @llua - Great find. I think I am running into the same issue, which is apparently a problem with Bash. Here's a similar report on the Red Hat bug tracker (linked to from that thread). For the record, I am running GNU bash, version 4.1.2(1)-release, which predates the shellshock fixes discussed in that thread by a few years. So perhaps it's not exactly the same issue. I should try with the latest release of Bash to see if this has been fixed.

    – Nick Chammas
    May 29 '15 at 22:22











  • Wow, this is weird. If I upgrade to the latest (I think) release, 4.3.30(1)-release and try the original snippet from my question, I now get: /bin/bash: line 1: stupid: command not found. So now it looks like bash and not sh is running, which is good, but the function is no longer accessible.

    – Nick Chammas
    May 29 '15 at 22:49











  • Even weirder on Bash 4.3.30: If I submit bash -c 'stupid' to at instead of just stupid, I get the original syntax error message with sh:. I'm lost now. ¯_(ツ)_/¯

    – Nick Chammas
    May 29 '15 at 22:51













5












5








5








I want to execute a Bash function at a scheduled time. I think the right tool for this is the at command.



However, it doesn't seem to be working.



function stupid () 
date


export -f stupid

cat << EOM | at now + 1 minute
stupid
EOM


After waiting the minute, I check my mail and this is the error I see:



sh: line 41: syntax error near unexpected token `=() date"
"'
sh: line 41: `"}; export BASH_FUNC_stupid()'


I don't understand what's going wrong here, especially since I know the function works.



$ stupid
Fri May 29 21:05:38 UTC 2015


Looking at the error, I think the incorrect shell is being used to execute the function (sh as opposed to bash), but if I check $SHELL I see it points to /bin/bash, and the man page for at says:



$ echo $SHELL
/bin/bash
$ man at

...

SHELL The value of the SHELL environment variable at the time
of at invocation will determine which shell is used to
execute the at job commands.


So Bash should be the shell running my function.



What going on here? Is there a way to get my Bash function to run with at?










share|improve this question
















I want to execute a Bash function at a scheduled time. I think the right tool for this is the at command.



However, it doesn't seem to be working.



function stupid () 
date


export -f stupid

cat << EOM | at now + 1 minute
stupid
EOM


After waiting the minute, I check my mail and this is the error I see:



sh: line 41: syntax error near unexpected token `=() date"
"'
sh: line 41: `"}; export BASH_FUNC_stupid()'


I don't understand what's going wrong here, especially since I know the function works.



$ stupid
Fri May 29 21:05:38 UTC 2015


Looking at the error, I think the incorrect shell is being used to execute the function (sh as opposed to bash), but if I check $SHELL I see it points to /bin/bash, and the man page for at says:



$ echo $SHELL
/bin/bash
$ man at

...

SHELL The value of the SHELL environment variable at the time
of at invocation will determine which shell is used to
execute the at job commands.


So Bash should be the shell running my function.



What going on here? Is there a way to get my Bash function to run with at?







bash environment-variables function at






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 29 '15 at 22:43









Gilles

538k12810881606




538k12810881606










asked May 29 '15 at 21:12









Nick ChammasNick Chammas

1286




1286







  • 1





    lists.gnu.org/archive/html/bug-bash/2014-09/msg00251.html

    – llua
    May 29 '15 at 21:56











  • @llua - Great find. I think I am running into the same issue, which is apparently a problem with Bash. Here's a similar report on the Red Hat bug tracker (linked to from that thread). For the record, I am running GNU bash, version 4.1.2(1)-release, which predates the shellshock fixes discussed in that thread by a few years. So perhaps it's not exactly the same issue. I should try with the latest release of Bash to see if this has been fixed.

    – Nick Chammas
    May 29 '15 at 22:22











  • Wow, this is weird. If I upgrade to the latest (I think) release, 4.3.30(1)-release and try the original snippet from my question, I now get: /bin/bash: line 1: stupid: command not found. So now it looks like bash and not sh is running, which is good, but the function is no longer accessible.

    – Nick Chammas
    May 29 '15 at 22:49











  • Even weirder on Bash 4.3.30: If I submit bash -c 'stupid' to at instead of just stupid, I get the original syntax error message with sh:. I'm lost now. ¯_(ツ)_/¯

    – Nick Chammas
    May 29 '15 at 22:51












  • 1





    lists.gnu.org/archive/html/bug-bash/2014-09/msg00251.html

    – llua
    May 29 '15 at 21:56











  • @llua - Great find. I think I am running into the same issue, which is apparently a problem with Bash. Here's a similar report on the Red Hat bug tracker (linked to from that thread). For the record, I am running GNU bash, version 4.1.2(1)-release, which predates the shellshock fixes discussed in that thread by a few years. So perhaps it's not exactly the same issue. I should try with the latest release of Bash to see if this has been fixed.

    – Nick Chammas
    May 29 '15 at 22:22











  • Wow, this is weird. If I upgrade to the latest (I think) release, 4.3.30(1)-release and try the original snippet from my question, I now get: /bin/bash: line 1: stupid: command not found. So now it looks like bash and not sh is running, which is good, but the function is no longer accessible.

    – Nick Chammas
    May 29 '15 at 22:49











  • Even weirder on Bash 4.3.30: If I submit bash -c 'stupid' to at instead of just stupid, I get the original syntax error message with sh:. I'm lost now. ¯_(ツ)_/¯

    – Nick Chammas
    May 29 '15 at 22:51







1




1





lists.gnu.org/archive/html/bug-bash/2014-09/msg00251.html

– llua
May 29 '15 at 21:56





lists.gnu.org/archive/html/bug-bash/2014-09/msg00251.html

– llua
May 29 '15 at 21:56













@llua - Great find. I think I am running into the same issue, which is apparently a problem with Bash. Here's a similar report on the Red Hat bug tracker (linked to from that thread). For the record, I am running GNU bash, version 4.1.2(1)-release, which predates the shellshock fixes discussed in that thread by a few years. So perhaps it's not exactly the same issue. I should try with the latest release of Bash to see if this has been fixed.

– Nick Chammas
May 29 '15 at 22:22





@llua - Great find. I think I am running into the same issue, which is apparently a problem with Bash. Here's a similar report on the Red Hat bug tracker (linked to from that thread). For the record, I am running GNU bash, version 4.1.2(1)-release, which predates the shellshock fixes discussed in that thread by a few years. So perhaps it's not exactly the same issue. I should try with the latest release of Bash to see if this has been fixed.

– Nick Chammas
May 29 '15 at 22:22













Wow, this is weird. If I upgrade to the latest (I think) release, 4.3.30(1)-release and try the original snippet from my question, I now get: /bin/bash: line 1: stupid: command not found. So now it looks like bash and not sh is running, which is good, but the function is no longer accessible.

– Nick Chammas
May 29 '15 at 22:49





Wow, this is weird. If I upgrade to the latest (I think) release, 4.3.30(1)-release and try the original snippet from my question, I now get: /bin/bash: line 1: stupid: command not found. So now it looks like bash and not sh is running, which is good, but the function is no longer accessible.

– Nick Chammas
May 29 '15 at 22:49













Even weirder on Bash 4.3.30: If I submit bash -c 'stupid' to at instead of just stupid, I get the original syntax error message with sh:. I'm lost now. ¯_(ツ)_/¯

– Nick Chammas
May 29 '15 at 22:51





Even weirder on Bash 4.3.30: If I submit bash -c 'stupid' to at instead of just stupid, I get the original syntax error message with sh:. I'm lost now. ¯_(ツ)_/¯

– Nick Chammas
May 29 '15 at 22:51










2 Answers
2






active

oldest

votes


















10














Bash functions are exported via the environment. The at command makes the environment, the umask and the current directory of the calling process available to the script by generating shell code that reproduces the environment. The script executed by your at job is something like this:



#!/bin/bash
umask 022
cd /home/nick
PATH=/usr/local/bin:/usr/bin:/bin; export PATH
HOME=/home/nick; export HOME

stupid


Under older versions of bash, functions were exported as a variable with the name of the function and a value starting with () and consisting of code to define the function, e.g.



stupid="() 
date
"; export stupid


This made many scenarios vulnerable to a security hole, the Shellshock bug (found by Stéphane Chazelas), which allowed anyone able to inject the content of an environment variable under any name to execute arbitrary code in a bash script. Versions of bash where with a Shellshock fix use a different way: they store the function definition in a variable whose name contains characters that are not found in environment variables and that shells do not parse as assignments.



BASH_FUNC_stupid%%="() 
date
"; export stupid


Due to the %, this is not valid sh syntax, not even in bash, so the at job fails, whether it even attempts to use the function or not. The Debian version of at, which is used in many Linux distributions, was changed in version 3.16 to export only variables that have valid names in shell scripts. Thus newer versions of at don't pass post-Shellshock bash exported functions through, whereas older ones error out.



Even with pre-Shellshock versions of bash, the exported function only works in bash scripts launched from the at job, not in the at job itself. In the at job itself, even if it's executed by bash, stupid is just another environment variable; bash only imports functions when it starts.



To export functions to an at job regardless of the bash or at version, put them in a file and source that file from your job, or include them directly in your job. To print out all defined functions in a format that can be read back, use declare -f.



 declare -f; cat << EOM; | at now + 1 minute
stupid
EOM





share|improve this answer

























  • Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

    – Nick Chammas
    May 30 '15 at 22:07











  • @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

    – Gilles
    May 30 '15 at 22:20











  • at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

    – Nick Chammas
    Jun 1 '15 at 20:08


















0














Well, you already know you get mail. That's pretty cool, because you definitely can execute a bash function when mail arrives.



This is from man bash:




  • $MAILPATH




    • A colon-separated list of filenames to be checked for mail. The message to be printed when mail arrives in a particular file may be specified by separating the filename from the message with a ?. When used in the text of the message, $_ expands to the name of the current mailfile. Example:



      MAILPATH='/var/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'


    • bash supplies a default value for this variable, but the location of the user mail files that it uses is system dependent (e.g., /var/mail/$USER).



Incidentally, $_ is not the only expansion that might occur in that context - you can expand practically anything, to include command substitutions. In fact, you don't necessarily need to print anything at all. And the files don't necessarily need to contain mail either - the shell will attempt to notify when a check performed every $MAILCHECK seconds indicates a file has been modified since it last had a look.



Still though, the way shells handle $MAILxxxx is usually dependent on prompts - which is to say that regardless of $MAILCHECK's value if you don't pull a new prompt at the right time you don't get notified - and won't until you trigger the next prompt. I'm not certain about this, but it maybe set -b would affect that.



In any case, there is more than one way to do that kind of thing. Perhaps most obvious would be to use a signal - schedule an at job like:



echo kill -USR1 "$$" | at now + 1 minute
trap some_func USR1


And see what happens.






share|improve this answer






















    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f206405%2fcan-you-execute-a-bash-function-with-the-at-command%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    10














    Bash functions are exported via the environment. The at command makes the environment, the umask and the current directory of the calling process available to the script by generating shell code that reproduces the environment. The script executed by your at job is something like this:



    #!/bin/bash
    umask 022
    cd /home/nick
    PATH=/usr/local/bin:/usr/bin:/bin; export PATH
    HOME=/home/nick; export HOME

    stupid


    Under older versions of bash, functions were exported as a variable with the name of the function and a value starting with () and consisting of code to define the function, e.g.



    stupid="() 
    date
    "; export stupid


    This made many scenarios vulnerable to a security hole, the Shellshock bug (found by Stéphane Chazelas), which allowed anyone able to inject the content of an environment variable under any name to execute arbitrary code in a bash script. Versions of bash where with a Shellshock fix use a different way: they store the function definition in a variable whose name contains characters that are not found in environment variables and that shells do not parse as assignments.



    BASH_FUNC_stupid%%="() 
    date
    "; export stupid


    Due to the %, this is not valid sh syntax, not even in bash, so the at job fails, whether it even attempts to use the function or not. The Debian version of at, which is used in many Linux distributions, was changed in version 3.16 to export only variables that have valid names in shell scripts. Thus newer versions of at don't pass post-Shellshock bash exported functions through, whereas older ones error out.



    Even with pre-Shellshock versions of bash, the exported function only works in bash scripts launched from the at job, not in the at job itself. In the at job itself, even if it's executed by bash, stupid is just another environment variable; bash only imports functions when it starts.



    To export functions to an at job regardless of the bash or at version, put them in a file and source that file from your job, or include them directly in your job. To print out all defined functions in a format that can be read back, use declare -f.



     declare -f; cat << EOM; | at now + 1 minute
    stupid
    EOM





    share|improve this answer

























    • Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

      – Nick Chammas
      May 30 '15 at 22:07











    • @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

      – Gilles
      May 30 '15 at 22:20











    • at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

      – Nick Chammas
      Jun 1 '15 at 20:08















    10














    Bash functions are exported via the environment. The at command makes the environment, the umask and the current directory of the calling process available to the script by generating shell code that reproduces the environment. The script executed by your at job is something like this:



    #!/bin/bash
    umask 022
    cd /home/nick
    PATH=/usr/local/bin:/usr/bin:/bin; export PATH
    HOME=/home/nick; export HOME

    stupid


    Under older versions of bash, functions were exported as a variable with the name of the function and a value starting with () and consisting of code to define the function, e.g.



    stupid="() 
    date
    "; export stupid


    This made many scenarios vulnerable to a security hole, the Shellshock bug (found by Stéphane Chazelas), which allowed anyone able to inject the content of an environment variable under any name to execute arbitrary code in a bash script. Versions of bash where with a Shellshock fix use a different way: they store the function definition in a variable whose name contains characters that are not found in environment variables and that shells do not parse as assignments.



    BASH_FUNC_stupid%%="() 
    date
    "; export stupid


    Due to the %, this is not valid sh syntax, not even in bash, so the at job fails, whether it even attempts to use the function or not. The Debian version of at, which is used in many Linux distributions, was changed in version 3.16 to export only variables that have valid names in shell scripts. Thus newer versions of at don't pass post-Shellshock bash exported functions through, whereas older ones error out.



    Even with pre-Shellshock versions of bash, the exported function only works in bash scripts launched from the at job, not in the at job itself. In the at job itself, even if it's executed by bash, stupid is just another environment variable; bash only imports functions when it starts.



    To export functions to an at job regardless of the bash or at version, put them in a file and source that file from your job, or include them directly in your job. To print out all defined functions in a format that can be read back, use declare -f.



     declare -f; cat << EOM; | at now + 1 minute
    stupid
    EOM





    share|improve this answer

























    • Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

      – Nick Chammas
      May 30 '15 at 22:07











    • @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

      – Gilles
      May 30 '15 at 22:20











    • at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

      – Nick Chammas
      Jun 1 '15 at 20:08













    10












    10








    10







    Bash functions are exported via the environment. The at command makes the environment, the umask and the current directory of the calling process available to the script by generating shell code that reproduces the environment. The script executed by your at job is something like this:



    #!/bin/bash
    umask 022
    cd /home/nick
    PATH=/usr/local/bin:/usr/bin:/bin; export PATH
    HOME=/home/nick; export HOME

    stupid


    Under older versions of bash, functions were exported as a variable with the name of the function and a value starting with () and consisting of code to define the function, e.g.



    stupid="() 
    date
    "; export stupid


    This made many scenarios vulnerable to a security hole, the Shellshock bug (found by Stéphane Chazelas), which allowed anyone able to inject the content of an environment variable under any name to execute arbitrary code in a bash script. Versions of bash where with a Shellshock fix use a different way: they store the function definition in a variable whose name contains characters that are not found in environment variables and that shells do not parse as assignments.



    BASH_FUNC_stupid%%="() 
    date
    "; export stupid


    Due to the %, this is not valid sh syntax, not even in bash, so the at job fails, whether it even attempts to use the function or not. The Debian version of at, which is used in many Linux distributions, was changed in version 3.16 to export only variables that have valid names in shell scripts. Thus newer versions of at don't pass post-Shellshock bash exported functions through, whereas older ones error out.



    Even with pre-Shellshock versions of bash, the exported function only works in bash scripts launched from the at job, not in the at job itself. In the at job itself, even if it's executed by bash, stupid is just another environment variable; bash only imports functions when it starts.



    To export functions to an at job regardless of the bash or at version, put them in a file and source that file from your job, or include them directly in your job. To print out all defined functions in a format that can be read back, use declare -f.



     declare -f; cat << EOM; | at now + 1 minute
    stupid
    EOM





    share|improve this answer















    Bash functions are exported via the environment. The at command makes the environment, the umask and the current directory of the calling process available to the script by generating shell code that reproduces the environment. The script executed by your at job is something like this:



    #!/bin/bash
    umask 022
    cd /home/nick
    PATH=/usr/local/bin:/usr/bin:/bin; export PATH
    HOME=/home/nick; export HOME

    stupid


    Under older versions of bash, functions were exported as a variable with the name of the function and a value starting with () and consisting of code to define the function, e.g.



    stupid="() 
    date
    "; export stupid


    This made many scenarios vulnerable to a security hole, the Shellshock bug (found by Stéphane Chazelas), which allowed anyone able to inject the content of an environment variable under any name to execute arbitrary code in a bash script. Versions of bash where with a Shellshock fix use a different way: they store the function definition in a variable whose name contains characters that are not found in environment variables and that shells do not parse as assignments.



    BASH_FUNC_stupid%%="() 
    date
    "; export stupid


    Due to the %, this is not valid sh syntax, not even in bash, so the at job fails, whether it even attempts to use the function or not. The Debian version of at, which is used in many Linux distributions, was changed in version 3.16 to export only variables that have valid names in shell scripts. Thus newer versions of at don't pass post-Shellshock bash exported functions through, whereas older ones error out.



    Even with pre-Shellshock versions of bash, the exported function only works in bash scripts launched from the at job, not in the at job itself. In the at job itself, even if it's executed by bash, stupid is just another environment variable; bash only imports functions when it starts.



    To export functions to an at job regardless of the bash or at version, put them in a file and source that file from your job, or include them directly in your job. To print out all defined functions in a format that can be read back, use declare -f.



     declare -f; cat << EOM; | at now + 1 minute
    stupid
    EOM






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 31 at 16:04









    Stephen Kitt

    173k24391467




    173k24391467










    answered May 29 '15 at 23:35









    GillesGilles

    538k12810881606




    538k12810881606












    • Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

      – Nick Chammas
      May 30 '15 at 22:07











    • @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

      – Gilles
      May 30 '15 at 22:20











    • at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

      – Nick Chammas
      Jun 1 '15 at 20:08

















    • Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

      – Nick Chammas
      May 30 '15 at 22:07











    • @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

      – Gilles
      May 30 '15 at 22:20











    • at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

      – Nick Chammas
      Jun 1 '15 at 20:08
















    Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

    – Nick Chammas
    May 30 '15 at 22:07





    Thank you for the thorough answer and history behind this behavior. One thing I think this answer doesn't explain, is why sh shows up in the error messages when $SHELL is correctly set to /bin/bash and that is supposedly what determines which shell executes the job. That just may be another artifact of the older version of Bash I was using. But in any case, it sounds like the headache-free solution to do what I want is to put my functions in a file and source them from the job, as you recommend.

    – Nick Chammas
    May 30 '15 at 22:07













    @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

    – Gilles
    May 30 '15 at 22:20





    @NickChammas What version of at do you have, on what distribution? The one maintained by Debian and used by many Linux distributions (and I think shared common ancestry with *BSD) always runs the supplied code with sh. It tells me warning: commands will be executed using /bin/sh when I run it. Given the passage you quote from your man page, you're using a different or patched version, which come to think of it might mean that it works differently (though with the same symptoms here).

    – Gilles
    May 30 '15 at 22:20













    at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

    – Nick Chammas
    Jun 1 '15 at 20:08





    at -V gives 3.1.10. I'm running on Amazon Linux AMI release 2013.03.

    – Nick Chammas
    Jun 1 '15 at 20:08













    0














    Well, you already know you get mail. That's pretty cool, because you definitely can execute a bash function when mail arrives.



    This is from man bash:




    • $MAILPATH




      • A colon-separated list of filenames to be checked for mail. The message to be printed when mail arrives in a particular file may be specified by separating the filename from the message with a ?. When used in the text of the message, $_ expands to the name of the current mailfile. Example:



        MAILPATH='/var/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'


      • bash supplies a default value for this variable, but the location of the user mail files that it uses is system dependent (e.g., /var/mail/$USER).



    Incidentally, $_ is not the only expansion that might occur in that context - you can expand practically anything, to include command substitutions. In fact, you don't necessarily need to print anything at all. And the files don't necessarily need to contain mail either - the shell will attempt to notify when a check performed every $MAILCHECK seconds indicates a file has been modified since it last had a look.



    Still though, the way shells handle $MAILxxxx is usually dependent on prompts - which is to say that regardless of $MAILCHECK's value if you don't pull a new prompt at the right time you don't get notified - and won't until you trigger the next prompt. I'm not certain about this, but it maybe set -b would affect that.



    In any case, there is more than one way to do that kind of thing. Perhaps most obvious would be to use a signal - schedule an at job like:



    echo kill -USR1 "$$" | at now + 1 minute
    trap some_func USR1


    And see what happens.






    share|improve this answer



























      0














      Well, you already know you get mail. That's pretty cool, because you definitely can execute a bash function when mail arrives.



      This is from man bash:




      • $MAILPATH




        • A colon-separated list of filenames to be checked for mail. The message to be printed when mail arrives in a particular file may be specified by separating the filename from the message with a ?. When used in the text of the message, $_ expands to the name of the current mailfile. Example:



          MAILPATH='/var/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'


        • bash supplies a default value for this variable, but the location of the user mail files that it uses is system dependent (e.g., /var/mail/$USER).



      Incidentally, $_ is not the only expansion that might occur in that context - you can expand practically anything, to include command substitutions. In fact, you don't necessarily need to print anything at all. And the files don't necessarily need to contain mail either - the shell will attempt to notify when a check performed every $MAILCHECK seconds indicates a file has been modified since it last had a look.



      Still though, the way shells handle $MAILxxxx is usually dependent on prompts - which is to say that regardless of $MAILCHECK's value if you don't pull a new prompt at the right time you don't get notified - and won't until you trigger the next prompt. I'm not certain about this, but it maybe set -b would affect that.



      In any case, there is more than one way to do that kind of thing. Perhaps most obvious would be to use a signal - schedule an at job like:



      echo kill -USR1 "$$" | at now + 1 minute
      trap some_func USR1


      And see what happens.






      share|improve this answer

























        0












        0








        0







        Well, you already know you get mail. That's pretty cool, because you definitely can execute a bash function when mail arrives.



        This is from man bash:




        • $MAILPATH




          • A colon-separated list of filenames to be checked for mail. The message to be printed when mail arrives in a particular file may be specified by separating the filename from the message with a ?. When used in the text of the message, $_ expands to the name of the current mailfile. Example:



            MAILPATH='/var/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'


          • bash supplies a default value for this variable, but the location of the user mail files that it uses is system dependent (e.g., /var/mail/$USER).



        Incidentally, $_ is not the only expansion that might occur in that context - you can expand practically anything, to include command substitutions. In fact, you don't necessarily need to print anything at all. And the files don't necessarily need to contain mail either - the shell will attempt to notify when a check performed every $MAILCHECK seconds indicates a file has been modified since it last had a look.



        Still though, the way shells handle $MAILxxxx is usually dependent on prompts - which is to say that regardless of $MAILCHECK's value if you don't pull a new prompt at the right time you don't get notified - and won't until you trigger the next prompt. I'm not certain about this, but it maybe set -b would affect that.



        In any case, there is more than one way to do that kind of thing. Perhaps most obvious would be to use a signal - schedule an at job like:



        echo kill -USR1 "$$" | at now + 1 minute
        trap some_func USR1


        And see what happens.






        share|improve this answer













        Well, you already know you get mail. That's pretty cool, because you definitely can execute a bash function when mail arrives.



        This is from man bash:




        • $MAILPATH




          • A colon-separated list of filenames to be checked for mail. The message to be printed when mail arrives in a particular file may be specified by separating the filename from the message with a ?. When used in the text of the message, $_ expands to the name of the current mailfile. Example:



            MAILPATH='/var/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'


          • bash supplies a default value for this variable, but the location of the user mail files that it uses is system dependent (e.g., /var/mail/$USER).



        Incidentally, $_ is not the only expansion that might occur in that context - you can expand practically anything, to include command substitutions. In fact, you don't necessarily need to print anything at all. And the files don't necessarily need to contain mail either - the shell will attempt to notify when a check performed every $MAILCHECK seconds indicates a file has been modified since it last had a look.



        Still though, the way shells handle $MAILxxxx is usually dependent on prompts - which is to say that regardless of $MAILCHECK's value if you don't pull a new prompt at the right time you don't get notified - and won't until you trigger the next prompt. I'm not certain about this, but it maybe set -b would affect that.



        In any case, there is more than one way to do that kind of thing. Perhaps most obvious would be to use a signal - schedule an at job like:



        echo kill -USR1 "$$" | at now + 1 minute
        trap some_func USR1


        And see what happens.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered May 30 '15 at 5:50









        mikeservmikeserv

        45.7k668159




        45.7k668159



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f206405%2fcan-you-execute-a-bash-function-with-the-at-command%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?