Need help on use of timeout utility in shell script

I’d appreciate some guidance from someone who understands shell (bash) scripting better than I, since I obviously don’t understand it much at all.

What I want to do is write a small script that I can execute conveniently from a crontab entry so that I can start a webcam recording some video at a specific time and do that for a set period and then stop. To do this, I tried a script that uses the timeout utility, which is supposed to just take as inputs a duration and a command to run.

The critical line in the script says:


   timeout $duration "ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile"

Called with, e.g., the parameters 15s 10 960x720 avi, the script produces this error:


   timeout: failed to run command ‘ffmpeg -y -f v4l2 -r 10 -s 960x720 -i /dev/video0 /home/maabaum/201303151028_video.avi’: No such file or directory

I believe the problem here is that I am somehow not passing the actual command – everything beginning with "ffmpeg … – to timeout properly. The problem is that nothing I can think of works. If I omit the double-quotes, timeout runs properly and calls ffmpeg, BUT NONE OF THE PARAMETERS ON THE COMMAND LINE GET PASSED TO ffmpeg, so it just sits there doing nothing until the timeout times out.

I’ve tried single quotes – fails, of course because the variables aren’t instantiated. I’ve tried back-ticks, I’ve tried quoting different sections …

What am I doing wrong?

This is not mission critical, because the script works if I remove the timeout feature and instead move that into the command-line in the crontab, but it’s just annoying that I can’t figure out the problem.

tnx
maabaum

Rule #1 of cron: Always, everywhere, use absolute paths if possible.
Rule #2 of cron: Use relative paths if absolute paths are not feasible.
Rule #3 of cron: No, really, do not rely on $PATH or similar.

So… put in /usr/bin/ffmpeg instead of ‘ffmpeg’ and see if that helps.

Good luck.

maabaum wrote:
> I believe the problem here is that I am somehow not passing the actual
> command – everything beginning with "ffmpeg … – to timeout properly.
> The problem is that nothing I can think of works. If I omit the
> double-quotes, timeout runs properly and calls ffmpeg, BUT NONE OF THE
> PARAMETERS ON THE COMMAND LINE GET PASSED TO ffmpeg, so it just sits
> there doing nothing until the timeout times out.
>
> I’ve tried single quotes – fails, of course because the variables
> aren’t instantiated. I’ve tried back-ticks, I’ve tried quoting different
> sections …

Show us the results of running the various variants of the command from
the shell instead of in a crontab. You can use some innocuous command
instead of ffmpeg (e.g. timeout 15s date --version). Please use code tags.

CLOSED. Will be moved to Development > Programming/Scripting.

Moved from applications and open again.

That sounds like solid advice, thanks, but it’s not the problem here. This issue never gets as far as cron. The script itself fails.
maab

As you ask for guidance…

You talk about not understanding bash, but this hasn’t much to do with bash. You execute the timeout command:

SYNOPSIS

timeout [OPTION] DURATION COMMAND [ARG]…
timeout [OPTION]

Which means that the argument “ffmpeg …” must be a command. And when timeout says that it can not find it, it most probably means it can not find the file ffmpeg.

Most probably when you type

ffmpeg

it will be found. But that is because of the value of the PATH variable when you type this. Thus when a file that should be a command can not be found, there must be something with the path leading to it. As advised above, use the complete path in the command.

I write this because you ask for guidance. The solution was already given above. But the guidance is that you should try to understand what the different partners are in what you do. What does the shell do, how inetrpretes it all the “words” in the command line it reads. What is timeout and what should it do, what are the arguments it gets offered by the shell on execution. Then there is ffmpeg, what are the arguments it gets.
And the the crucial question: who is giving me that error message. That might not be clear from the start, but you should contemplate all possibilities: what if bash gives it, what if timeout gives it …

Consult the man pages, those of cron, bash, timeout and ffmpeg. The one of cron should already have given you a clue.

It is hard work and the learning curve is steep. Have a nice weekend

(End of todays lesson). rotfl!

hcvv wrote:
> As you ask for guidance…
>
> You talk about not understanding bash, but this hasn’t much to do with
> bash. You execute the timeout command:
>> SYNOPSIS
>>
>> timeout [OPTION] DURATION COMMAND [ARG]…
>> timeout [OPTION]
> Which means that the argument “ffmpeg …” must be a command.

Yes, ffmpeg is a command but no …

> And
> when timeout says that it can not find it, it most probably means it can
> not find the file ffmpeg.

… that is not what the rejection means.

If you read carefully, I think you’ll find it didn’t say it couldn’t
find ffmpeg, it said it couldn’t find a command with a rather long name
of which the first six characters were indeed ‘ffmpeg’ but the seventh
character was a space and the succeeding characters looked rather like
arguments to the ffmpeg command but were in fact part of the name of the
command with the long name, because of the presence of unwanted quotes
on the command line.

Hence my request to the OP to post the actual output of all variants of
the command so we can see what is happening.

I wasn’t clear. Everything I original posted was the result of running it from the shell outside of crontab.

Yes, well, it’s kind of like I said.

  1. Use no quotes at all: timeout invokes and correctly times ffmpeg, but no command-line inputs seem to get passed to to ffmpeg, so it does nothing.
  2. Put double quotes around the parameters passed to ffmpeg: Same as case 1.
  3. Use single quotes around ‘ffmpeg …’: Same error message as reported in my original post, except the variable substitution doesn’t happen, of course.
  4. Put double quotes around everything following the command timeout: Get the timeout improper invocation message (“time timeout --help for more information”)
  5. Put double quotes around the whole **** line: Error from script saying “No such file or directory”. But all the variables including the file name are expanded correctly.
  6. Put backticks (`) around whole line: Same as case 1
  7. Put backticks around just the ffmpeg invocation: In this case, the ffmpeg command gets run first as of course it would, and it plans to run forever. Once you halt it from the keyboard, then control passes to the timeout command, which compains about improper inputs.

Substituting an innocuous command like:

timeout $duration date

or

timeout $duration sleep 60

works just fine.

maab

maabaum wrote:
> djh-novell;2535597 Wrote:
>> maabaum wrote:
>>> I believe the problem here is that I am somehow not passing the
>> actual
>>> command – everything beginning with "ffmpeg … – to timeout
>> properly.
>>> The problem is that nothing I can think of works. If I omit the
>>> double-quotes, timeout runs properly and calls ffmpeg, BUT NONE OF
>> THE
>>> PARAMETERS ON THE COMMAND LINE GET PASSED TO ffmpeg, so it just sits
>>> there doing nothing until the timeout times out.
>>>
>>> I’ve tried single quotes – fails, of course because the variables
>>> aren’t instantiated. I’ve tried back-ticks, I’ve tried quoting
>> different
>>> sections …
>> Show us the results of running the various variants of the command from
>> the shell instead of in a crontab. You can use some innocuous command
>> instead of ffmpeg (e.g. timeout 15s date --version). Please use code
>> tags.
>
> I wasn’t clear. Everything I original posted was the result of running
> it from the shell outside of crontab.

PLEASE post the actual output of the session, not your paraphrase.

> Yes, well, it’s kind of like I said.
> 1. Use no quotes at all: timeout invokes and correctly times ffmpeg,
> but no command-line inputs seem to get passed to to ffmpeg, so it does
> nothing.
> 2. Put double quotes around the parameters passed to ffmpeg: Same as
> case 1.
> 3. Use single quotes around ‘ffmpeg …’: Same error message as
> reported in my original post, except the variable substitution doesn’t
> happen, of course.
> 4. Put double quotes around everything following the command timeout:
> Get the timeout improper invocation message (“time timeout --help for
> more information”)
> 5. Put double quotes around the whole **** line: Error from script
> saying “No such file or directory”. But all the variables including the
> file name are expanded correctly.
> 6. Put backticks (`) around whole line: Same as case 1
> 7. Put backticks around just the ffmpeg invocation: In this case, the
> ffmpeg command gets run first as of course it would, and it plans to
> run forever. Once you halt it from the keyboard, then control passes to
> the timeout command, which compains about improper inputs.
>
> Substituting an innocuous command like:
>
> timeout $duration date
>
> or
>
> timeout $duration sleep 60
>
> works just fine.
>
> maab
>
>

I understand that you are trying to help, and I appreciate that. I also understand that “post the actual output” is a standard response in these cases. I honestly do not understand what that will tell you that I haven’t but okay, here it is:

Script line:


timeout $duration "/usr/bin/ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile"

Output:


timeout: failed to run command ‘/usr/bin/ffmpeg -y -f v4l2 -r 30 -s hd720 -i /dev/video0 /home/baum/201303151341_video.avi’: No such file or directory

Script line:


timeout $duration /usr/bin/ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile

Output:


ffmpeg version 1.1 Copyright (c) 2000-2013 the FFmpeg developers
  built on Jan  7 2013 20:40:56 with gcc 4.7 (SUSE Linux)
  configuration: --shlibdir=/usr/lib64 --prefix=/usr --mandir=/usr/share/man --libdir=/usr/lib64 --enable-shared --disable-static --enable-debug --disable-stripping --extra-cflags='-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -fPIC -I/usr/include/gsm' --enable-gpl --enable-x11grab --enable-version3 --enable-pthreads --enable-avfilter --enable-libpulse --enable-libvpx --enable-libopus --enable-libass --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libxvid --enable-libx264 --enable-libschroedinger --enable-libgsm --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-postproc --enable-libdc1394 --enable-librtmp --enable-libfreetype --enable-avresample --enable-libtwolame
  libavutil      52. 13.100 / 52. 13.100
  libavcodec     54. 86.100 / 54. 86.100
  libavformat    54. 59.106 / 54. 59.106
  libavdevice    54.  3.102 / 54.  3.102
  libavfilter     3. 32.100 /  3. 32.100
  libswscale      2.  1.103 /  2.  1.103
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
 until timeout expires ]

Script line:


timeout "$duration /usr/bin/ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile"

Output:


Try 'timeout --help' for more information.

Script line:


timeout $duration '/usr/bin/ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile'

Output:


timeout: failed to run command ‘/usr/bin/ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile’: No such file or directory

Script line:


timeout $duration /usr/bin/ffmpeg "-y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile"

Output:


ffmpeg version 1.1 Copyright (c) 2000-2013 the FFmpeg developers
  built on Jan  7 2013 20:40:56 with gcc 4.7 (SUSE Linux)
  configuration: --shlibdir=/usr/lib64 --prefix=/usr --mandir=/usr/share/man --libdir=/usr/lib64 --enable-shared --disable-static --enable-debug --disable-stripping --extra-cflags='-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -fPIC -I/usr/include/gsm' --enable-gpl --enable-x11grab --enable-version3 --enable-pthreads --enable-avfilter --enable-libpulse --enable-libvpx --enable-libopus --enable-libass --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libxvid --enable-libx264 --enable-libschroedinger --enable-libgsm --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-postproc --enable-libdc1394 --enable-librtmp --enable-libfreetype --enable-avresample --enable-libtwolame
  libavutil      52. 13.100 / 52. 13.100
  libavcodec     54. 86.100 / 54. 86.100
  libavformat    54. 59.106 / 54. 59.106
  libavdevice    54.  3.102 / 54.  3.102
  libavfilter     3. 32.100 /  3. 32.100
  libswscale      2.  1.103 /  2.  1.103
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
 until timeout expires ]

I should observe that in the two cases above where ffmpeg actually runs, that block of output is basically what the program produces up to the point where it starts processing something, which leads me to think that it’s missing the input/output instructions. If you run ffmpeg by itself from the command line with no additional parameters, you would get the blocks of info above together with these lines:


Hyper fast Audio and Video encoder
usage: ffmpeg [options] [infile options] -i infile]... {[outfile options] outfile}...

Use -h to get full help or, even better, run 'man ffmpeg'

ALSO NOTE that in response to other posts, I have included in these examples the absolute path to the program in case the script for some reason ignores the path variable. ffmpeg is installed to /usr/bin, which I have been led to believe is a fairly standard element in the path searched for executables.

Thanks,
maabaum

I wondered, you know, if timeout just ignored everything on the command line after the command itself, throwing away all the args (although the manpage says not…) but if I simply invoke the sequence from the command line, writing in all the variable values, it works fine:


~> timeout 15s /usr/bin/ffmpeg -y -f v4l2 -r 10 -s hd720 -i /dev/video0 $HOME/anothertest.avi
ffmpeg version 1.1 Copyright (c) 2000-2013 the FFmpeg developers
  built on Jan  7 2013 20:40:56 with gcc 4.7 (SUSE Linux)
  configuration: --shlibdir=/usr/lib64 --prefix=/usr --mandir=/usr/share/man --libdir=/usr/lib64 --enable-shared --disable-static --enable-debug --disable-stripping --extra-cflags='-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -fPIC -I/usr/include/gsm' --enable-gpl --enable-x11grab --enable-version3 --enable-pthreads --enable-avfilter --enable-libpulse --enable-libvpx --enable-libopus --enable-libass --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libxvid --enable-libx264 --enable-libschroedinger --enable-libgsm --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-postproc --enable-libdc1394 --enable-librtmp --enable-libfreetype --enable-avresample --enable-libtwolame
  libavutil      52. 13.100 / 52. 13.100
  libavcodec     54. 86.100 / 54. 86.100
  libavformat    54. 59.106 / 54. 59.106
  libavdevice    54.  3.102 / 54.  3.102
  libavfilter     3. 32.100 /  3. 32.100
  libswscale      2.  1.103 /  2.  1.103
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
[video4linux2,v4l2 @ 0x1c92980] The V4L2 driver changed the video from 1280x720 to 960x720
[video4linux2,v4l2 @ 0x1c92980] Estimating duration from bitrate, this may be inaccurate
Input #0, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 20069.176270, bitrate: 110592 kb/s
    Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 960x720, 110592 kb/s, 10 tbr, 1000k tbn, 10 tbc
Output #0, avi, to '/home/baum/anothertest.avi':
  Metadata:
    ISFT            : Lavf54.59.106
    Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 960x720, q=2-31, 200 kb/s, 10 tbn, 10 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo -> mpeg4)
Press [q] to stop, ?] for help
frame=  144 fps= 10 q=31.0 Lsize=     733kB time=00:00:14.40 bitrate= 416.7kbits/s    
video:724kB audio:0kB subtitle:0 global headers:0kB muxing overhead 1.243530%
Received signal 15: terminating.

I incautiously put in the wrong frame parameters but v4l2 helpfully corrected them on the fly.

maabaum

maabaum wrote:
> I understand that you are trying to help, and I appreciate that. I also
> understand that “post the actual output” is a standard response in these
> cases. I honestly do not understand what that will tell you that I
> haven’t but okay, here it is:

Well no, it wasn’t. Again you posted snippets - command lines with
variabls without showing the variable definitions, out put separate from
the command that caused it and so on.

The point is that you are the one that doesn’t understand, so don’t try
to outthink the people who are trying to help. Just try to help us help you.

maabaum wrote:
> I wondered, you know, if timeout just ignored everything on the command
> line after the command itself, throwing away all the args (although the
> manpage says not…)

Obviously not, since the examples I posted demonstrate that it does not.

> but if I simply invoke the sequence from the
> command line, writing in all the variable values, it works fine:

Well, surprise, surprise, not! Since you have still to post the code, we
can’t help you debug it, so you’re on your own.

Try not to be arrogant. You have clearly not read my responses carefully enough to be helpful. Or looked closely at the scripts and outputs I posted.

Thanks anyway. If I figure out what’s going on, I’ll post a follow-up for anyone interested.

maab

Sorry, I should not snap at you when you are just trying to feel your way through a fog of words and back-and-forth notes. Your idea, I imagine, is that there is some sort of error in the variable substitution in the script that cause the timeout command to throw away everything on the line following ‘ffmpeg’. Could be, I suppose, though I’m not quite sure how. This is the complete script as it now stands:

#!/bin/bash
# record_video duration framerate framesize vidtype

ARGS=4
E_WRONGARGS=65

# default values
timestamp=$(date +%Y%m%d%H%M)
vfilebase="-video."
vidtype="avi"
framerate=30
framesize=hd720
duration=15s

# check number of argument
if  $# -ne "$ARGS" ]
then
   echo "Usage: `basename $0` duration framerate framesize vidtype"
   echo "  Ex: `basename $0` 30m 30 1280x720 avi"
   echo "  These are the defaults. To keep a default, use '-'."
   exit $E_WRONGARGS
fi

if  "-" = "$1" ]
then
  :
else
  duration=$1
fi 

if  "-" = "$2" ]
then
  :
else
  framerate=$2
fi

if  "-" = "$3" ]
then
  :
else 
  framesize=$3
fi

if  "-" = "$4" ]
then
  :
else 
  vidtype=$4
fi

vfile=$timestamp$vfilebase$vidtype

timeout $duration "/usr/bin/ffmpeg -y -f v4l2 -r $framerate -s $framesize -i /dev/video0 $HOME/$vfile"

m

The problem is that you have a problem where you have thought about already for a long time. That means that when you present your problem, you will impress on us unintentional your way of thinking about this problem, the pathes you walked along during your searching and your conclusions.

Many years of debug experiences come together here in the forums. And these experiences tell us that we should:
a) take it for granted (so not to much) that those pathes shown by an OP are well trodden and thus do not lead to a solution;
b) stories told by an OP, but not backed by real computer facts (unabridged live listings) are not to be believed;
c) tryiing to help means asking for those things the OP did not get into, because the cause is almost certain something he did not even think about to research.

You should thus be prepared for helpers here to ask you things where you are sure there is nothing. Maybe there is not, but they want proof, not by you telling stories, but by seeing computer evidence. Refusing (or even being reserved) in answering will for sure frustrate your helper. Not only the one that directly asked something, but also others that see this happening and thus will simply go to another thread (or for lunch) and detach from your thread. Be glad when someone, maybe a bit irritated, asks again. Going away and leaving you on your own is much easier.

It is with the distance between all of us in space and time very difficult to have a precise and exact disussion. Sitting together at your PC would make everything so much easier. But this is how it is.

Well, now I’ve posted and wrapped in code tags just about everything I can think of it, so that should make it easier.

You know, that’s probably why I never got an answer to this question either:
https://forums.opensuse.org/english/get-technical-help-here/applications/479147-fiddly-emacs-diary-question.html

maab

I have posted something in the other one (no hurry to look at it, it will not realy solve your problem there :().

And about this one, I more or less have given up understanding what is and what isn’t working.

I see in the script you still have the "s around the ffmpeg command and it’s arguments. What I read from the timeout man page is that everything after COMMAND will be passed as ARGs to the command. Thus I see no need for them. But when you use them, you should be aware of the fact that now the whole “ffmpeg …” is offered as one argument to timeout as it’s second argument and thus as COMMAND. This means that timeout will use that whole string to find the command. And fails because ffmpeg … is no file at all (no such file or directory), only ffmpeg on his own is.
I repeat, why the "s???

And about your computer text within the CODE tags, we only see output. We do not see the prompt, the command and the prompt at the end. When I e.g. want to show my crontab, I do:

boven:~ # crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.HImFsK installed on Fri Jan 25 17:04:06 2013)
# (Cronie version 4.2)
*/5 0-6,23 * * *        /root/bin/nachtstop >/dev/null 2>&1

*/5 * * * *     /root/bin/wij

boven:~ #

which will show to all readers that I was root, that I was in root’s home directory, which command I exactly used, what the output was and that it is complete. All things you partly try to explain by telling things, but that are shown without doubt when posted as here. And that makes people suspicious. Not because they think that you are deliberately misleading hem, but because they feel uncertain about what they see. is this all, were there things changed (and yes, when there is the password for your wifi access point, you should make xxx of it, but you should also add a remark that you did).

And when you start it from the crontab, call the script with an absolute path, and redirect the output somewhere, either into the black hole (as shown in my first entry above) or in a file somewhere to be read later.

On 2013-03-18 22:06, hcvv wrote:
>
> maabaum;2537475 Wrote:

>> You know, that’s probably why I never got an answer to this question
>> either:

> I have posted something in the other one (no hurry to look at it, it
> will not realy solve your problem there :().

I’ll post here to say I concur with Henk.

On your post about emacs, I never said a word because I know next to
nothing about emacs. If I did know something, I would have commented
about the no code tags there, of course :-p

The subject line was enough to tell me to skip the posting, because it
was a correct subject line. Other people knowing about emacs may have
read it, but maybe they did not know about that particular problem.

> I see in the script you still have the "s around the ffmpeg command and

> I repeat, why the "s???

I agree with your diagnosis. To verify, I would have to run that script
assuming I had a similar hardware, and I don’t on this computer.

> And about your computer text within the CODE tags, we only see output.
> We do not see the prompt, the command and the prompt at the end. When I
> e.g. want to show my crontab, I do:

And I also have to agree with this. I would like to see in a block the
script being called complete with the output till the next prompt. Doing
it that way helps us to try to figure out what is happening.

Instead of saying “I run ls” and get a listing like this, instead post
it like this:


cer@Telcontar:~> ls p
p
cer@Telcontar:~>

Less descriptions, more facts :slight_smile:


Cheers / Saludos,

Carlos E. R.
(from 12.1 x86_64 “Asparagus” at Telcontar)