23

I have some commands in my .profile that I want to invoke from my crontab.

For example, if I have,

alias notify-me="~/bin/notify.pl -u user1"
alias notify-team="~/bin/notify.pl -u user1 user2 user3 user4 ...."

I'd like to just invoke the alias

0 11 * * * notify-team

so if the list in my .profile is updated, I don't have to update the crontab, too. However, I don't seem to be able to use aliases in my crontab. Is there a work around?

I tried the suggestions here to set up the environment (e.g. /bin/bash -lc and the script-wrapper script). It seems like that works for scripts but not aliases.

Any ideas?

Keith Bentrup
  • 699
  • 3
  • 8
  • 19
  • Thanks, all for the useful info. Couple possible solutions here including my own. I ultimately modified artifex's original idea to something more useful for my situation. Chris provided the necessary info to do it with separate scripts. – Keith Bentrup Mar 12 '10 at 23:22

7 Answers7

11

From the manpage regarding aliases:

Note aliases are not expanded by default in  non-interactive  shell,
and  it  can  be  enabled  by  setting  the 'expand_aliases'
shell option using shopt.

So try using shopt -s expand_aliases at the start of your sourcing script. This should let you use Warner's suggestion.

Christopher Karel
  • 6,442
  • 1
  • 26
  • 34
8

bash -c with "source" should work:

0 11 * * * bash -c "source .profile && notify-team"

this might also work. the period means "source"

0 11 * * * . .profile && notify-team
Collin Anderson
  • 401
  • 2
  • 6
  • 13
4

As Chris identified, the default shell option for non-interactive shells is to not expand aliases. Here's a solution I've found to work.

Write a script, enable the shell option, and source your aliases. Be particularly aware that .bashrc is sourced at execution, which is why it has to be sourced again after enabling expand_aliases.

My apologies for the initially incorrect recommendation. This was more obscure than I initially expected it to be.

Script:

#!/bin/bash
shopt -s expand_aliases
source /home/wmoore/.bashrc
notify-team
Warner
  • 23,440
  • 2
  • 57
  • 69
  • Thx, but I've tried that already. Can you confirm that it works on your system? I've also tried /bin/bash -lc source ~/.profile; notify-team and other variations. Also I prefer not to have a separate script for each alias. That defeats the purpose of avoiding duplication. – Keith Bentrup Mar 04 '10 at 19:03
  • I should have included the error from crontab: "command not found" on every variation that I've tried. – Keith Bentrup Mar 04 '10 at 19:05
  • Edited with a tested recommendation. – Warner Mar 04 '10 at 22:35
  • Thx for the updated example. I think if you add -l to your 1st line you can get rid of your 3rd. – Keith Bentrup Mar 06 '10 at 04:25
  • Ah, good call-- login shell would have expand_aliases enabled. – Warner Mar 06 '10 at 04:32
  • I'm not understanding "Be particularly aware that .bashrc is sourced at execution, which is why it has to be sourced again after enabling expand_aliases." What's the logic exactly? – qazwsx Apr 20 '14 at 16:47
  • Just adding this since I found it useful, you **must** add the `#!/bin/bash` part at the top of the script otherwise it won't work. You also need to make the script executable with `chmod +x` – Jens Bodal Nov 13 '17 at 08:24
  • Great answer, I really think this is the best way to set environment variables. The set_variables.sh file that get sourced can then be reused in other places. – gabn88 Nov 30 '19 at 15:39
1

I like artifex's idea of grabbing the alias from the file and then reusing it, since I couldn't find a way to expand/reuse aliases directly. (Other solutions still required another script.)

So I wrote this function and put it in my .profile:

grab-alias () { sed -n '/alias\s*'$1'\s*=/ {s/[^'\'']*.//;s/'\''\s*$//p}' /home/bentrupk/.profile; }

Then I was able to use it in my crontab for various aliases like this:

0 11 * * * /bin/bash -lc 'x=`grab-alias notify-team`; $x'
0 7 * * * /bin/bash -lc 'x=`grab-alias notify-me`; $x'

etc.

Yay, code reuse! Thanks, all.

Keith Bentrup
  • 699
  • 3
  • 8
  • 19
  • 3
    that is pure evil. – Justin Mar 06 '10 at 06:01
  • If I could use the alias directly, I would. That's the point of the question. You're welcome to propose another solution, but I'll take this solution over lots of 2-3 line files cluttering up a directory - which is what will happen as I add additional notification schemes or decide to reuse some of my other aliases. – Keith Bentrup Mar 06 '10 at 06:32
1

Really the simplest thing you could do would be to create

~/bin/notify-me with

#!/bin/sh
~/bin/notify.pl -u user1

~/bin/notify-team with

#!/bin/sh
~/bin/notify.pl -u user1 user2 user3 user4 ....

shell aliases are complicated to maintain and to integrate into other systems, as you've seen. the best thing to do is to turn them into full fledged commands that won't have funny environment issues.

Justin
  • 3,776
  • 15
  • 20
  • 1
    Thanks for suggestion, but I never thought aliases were hard to maintain, and I'd rather maintain 1 file of aliases then maintain lots of wrapper files. The problem was executing the aliases in a cron job. – Keith Bentrup Mar 06 '10 at 06:30
0

bash -ic "notify-team" is best option. It makes alias available in crontab. You may further add a & for background as we are using a 'interactive' shell with -i , but in reality not interacting with it.

-3
0 11 * * * bash -ic "notify-team" > /log/file

works for me