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
if (strcmp(argv[1], "-cron") == 0) { /* started from cron job */ }
and, of course, document the behaviour. – Counterreplyif( argc > 1 && ...
:-) – Lavella--cron
flag – Dorweilercron
process, but it's much more work. – Pilauargv[0]
. – Sareneisatty()
on thestdin
file descriptor might work. It won't specifically tell you it was run by cron, but at least whether it was run interactively. – Marchelle