Score:0

How to make timeout(1) behave in cron like it behaves in interactive shell

in flag

Running this command in an interactive bash:

$ timeout 1 sleep 2; echo $?
124

returns 124 after 1 second, as expected and as documented in timeout(1).

However, if I run the same as a cron job, or if I give that as a command string to bash, it does not:

$ bash -c "timeout 1 sleep 2; echo $?"
0

Adding -i to the bash invocation does not help, neither does using the --foreground parameter to timeout(1). I also tried the same with ksh and zsh, but always get the same result, so I guess it must be something inherent to the way timeout(1) works.

I searched the net a bit and found, that it could have to do with how the signalling proceeds through the process groups, but I could not find a solution how to make timeout work as expected in the non-interactive case.

Any hints on how I could achieve that? Ultimately what I want is to run a command in cron that is likely to block forever and I want to detect that case reliably.

diya avatar
la flag
I think that your problem is more in printing the timeout exit code rather than `timeout` not working in a cron invocation. - For example `bash -c "exitcode=$(timeout 1 sleep 2 ; echo $?); echo $exitcode"` should work as you intend. - - In general though when your batch job needs to do anything slightly more complicated than simply run on a particular schedule, don't try to run it directly from cron but write a simple shell script wrapper and call that from cron.
Sebastian Stark avatar
in flag
For me that command does not output anything. But thanks for the suggestion.
Score:1
in flag

You can try to run the command like this:

bash -c "timeout 1 sleep 2"; echo $?
Sebastian Stark avatar
in flag
That looks better. Can you explain that different behaviour?
Romeo Ninov avatar
in flag
FOr me it seems like echo print the error code of `timeout`, not `sleep`. But I am not sure :)
Romeo Ninov avatar
in flag
@SebastianStark, or maybe because `bash -c` IMHO run in subshell and ...
Score:1
fo flag

Due to the double quotes, $? is being expanded before the bash command is invoked. It is being replaced by the exit status of the previous command (which was the first exit $?)

A quick demo

bash -c 'exit 42'
bash -c "timeout 1 sleep 2; echo $?"   # => 42

The solution is to use single quotes so that the current interactive bash process does not expand the variable

bash -c 'timeout 1 sleep 2; echo $?'   # => 124
Sebastian Stark avatar
in flag
That's quit a stupid mistake from my side. Thanks for pointing this out. I will check my cronjob script and see if it has the same mistake and post an update to this question. Thank you!
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.