Is there a way to know when a C program has been launched by cron?

105 Views Asked by At

I have written a C utility that may be launched manually or on a regular basis, by a cron rule. Inside the C program I want to know if it was launched by a cron rule or not.

Reading the user name with getlogin_r renders the same username wether it is launched manually or by cron.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  char *username = malloc(80);
  getlogin_r(username, 80);
  printf("owner: %s\n", username);

  return 0;
}

Any idea?

1

There are 1 best solutions below

0
coterobarros On

Following user sj95126 suggestion, I found an indirect (but good enough) way of detecting if a program has been launched by cron or not.

When it comes to run a command-line present at the crontab, cron creates a non-interactive shell for it, i.e., one without standard input, standard output and standard error. This circumstance can be easily tested with the isatty() function from the unistd.h library.

This is a POC of the idea.

/* owner.c */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* return true if this process has been launched by cron */
/* cron is not directly identified but deduced from no having a tty */
int launched_bycron() {
  return (isatty(STDIN_FILENO) + isatty(STDOUT_FILENO) + isatty(STDERR_FILENO)) == 0;
}

int main() {
  /* print 1 if stdin, stdout or stderr exist */
  printf("stdin:    %d\n", isatty(STDIN_FILENO));  /* STDIN_FILENO = 0 */
  printf("stdout:   %d\n", isatty(STDOUT_FILENO)); /* STDIN_FILENO = 1 */
  printf("stderr:   %d\n", isatty(STDERR_FILENO)); /* STDIN_FILENO = 2 */

  /* get this process username */
  char *username = malloc(80);
  getlogin_r(username, 80);

  /* differentiate launching by cron from lauhcing by user */
  if (launched_bycron()) {
    printf("this was launched by cron\n");
  }
  else {
    printf("this was launched by %s\n", username);
  }

  return 0;
}

When launched manually the output is like this

$ ./owner
stdin:    1
stdout:   1
stderr:   1
this was launched by coterobarros

when launched by cron the output can still be captured piping the standard output to a file

crontab -l
* * * * * /usr/local/bin/owner > /tmp/owner.txt

and the content of the file is

$ cat /tmp/*.txt
stdin:    0
stdout:   0
stderr:   0
this was launched by cron

This link was very helpful too https://unix.stackexchange.com/questions/46789/check-if-script-is-started-by-cron-rather-than-invoked-manually