Output command result to file - batch-file

Windows cmd file has the following line
wget "http://ftp.gnu.org/gnu/wget/wget-1.5.3.tar.gz" -P C:\temp >> dld.log
After executing the dld.log file is empty.
What is wrong with output redirection?
It is necessary that the output of wget execution is written to the dld.log file

wget redirects output to stderr mostly to split off from the results data.
So direct answer to to make the current redirect code work is to use 2>&1 to direct sterr stream to stdout as in:
(wget "http://ftp.gnu.org/gnu/wget/wget-1.5.3.tar.gz" -P "C:\temp")>>dld.log 2>&1
However, wget has log functions built in which makes more sense. The switch is --output-file
wget "http://ftp.gnu.org/gnu/wget/wget-1.5.3.tar.gz" -P "C:\temp" --output-file=dld.log
See the wget manual for more info.

Related

Windows batch redirect output to console

The summary of this question is I have a command I'm running in batch, Some.exe args but it is not outputting to the console. It does however output to a text file if used like Some.exe args > test.txt. I've tried stuff like #Some.exe args and Some.exe args > CON to get it to output to the console, but neither seems to work.
Are there any other approaches which might work?
This follows on from a previous question I asked DOORS make console the interactive window.
I'm calling a program called DOORS through a batch script. It runs a simple script, hello.dxl that looks like
cout << "Hello world"
The batch script, Run.bat looks like
"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl
When this is run, no output appears on the screen and there are no popup windows or anything (if hello.dxl said print("Hello World") an interactive window would pop-up, but not with cout)
If I add > test.txt to the end of the command
"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl > test.txt
It outputs the Hello World to test.txt successfully. Something I noticed is when using print("Hello World") there was no output sent to the test.txt file and an interactive window popped up so it looks like cout is the way to go.
So I though the output might just not be being output anywhere, so I tried adding > CON instead to try to force it to go to the console.
"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl > CON
But that still resulted in a blank output.
I also tried adding an #, before the command, as suggested in this Batch - redirect program output to current console, like
#"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl
or
#"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl > CON
But no luck there either
I would have tried to reproduce this issue without DOORS but I don't know what is causing it in the first place.
Edit: I'm not really looking to use > test.txt & type test.txt as that is the current workaround I am using. But ideally I don't want it outputting to a text file
Turns out this approach has limited functionality, as soon as I tried opening a module, it made the interactive window pop up and no output was visible in the interactive window or the the console window
This is not an issue with the > test.txt & type test.txt workaround
Based on #PA.'s suggestion that the program is somehow preventing output to stdout but not if it was redirected, so I wrote a small C# console app which looks like
using System;
using System.Diagnostics;
using Process process = new();
process.EnableRaisingEvents = true;
process.ErrorDataReceived += ErrOut;
process.OutputDataReceived += StdOut;
process.StartInfo.FileName = args[0].Trim();
process.StartInfo.Arguments = args[1].Trim();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
static void ErrOut(object sender, DataReceivedEventArgs dataReceivedEventArgs)
{
if (dataReceivedEventArgs.Data != null)
{
Console.WriteLine(dataReceivedEventArgs.Data);
}
}
static void StdOut(object sender, DataReceivedEventArgs dataReceivedEventArgs)
{
if (dataReceivedEventArgs.Data != null)
{
Console.WriteLine(dataReceivedEventArgs.Data);
}
}
I then exported this to a single exe using the command
dotnet publish /p:DebugType=None /p:DebugSymbols=false /p:PublishReadyToRun=true /p:PublishSingleFile=true /p:PublishReadyToRunShowWarnings=true /p:PublishTrimmed=false /p:IncludeNativeLibrariesForSelfExtract=true /p:IncludeAllContentForSelfExtract=true "RedirectOutput.csproj" -o "." -c release
which I added then just added the folder with that exe in to my path environment variable.
Now I can just do
RedirectOutput "C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" "-u test -pass testPass -b hello.dxl"
and I get the desired output
This is more a workaround.
The idea is to a use a pipe program in order to redirect the output of the Windows program to the console:
SomeWinProg SomeArgs 2>>&1 | SomePipeProg PipeProgArgs
As a pipe program you may use a program that passes throug everything, like:
SomeWinProg SomeArgs 2>>&1 | findstr /r "/c:.*"
If this works or not depends on the Windows program.
Concerning the timing:
There may be some trouble when you have a long time running Windows program which produces sporadic output or when the output is done always to the same line (no line feeds, only carriage returns) and you want to have the output in real time.
In these cacses Windows programs like findstr or find are a little bit weak.
On github there is an implementation of mtee thats fits better:
SomeWinProg SomeArgs 2>>&1 | mtee nul

make wget fail silently, without needing user input

I have a batch script that makes backups from remote camera drives on a private network using wget:
echo off
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%i in (1 2 3 4 5) DO (
wget64 --http-user admin --http-password instar -r -l inf -nc -e robots=off --directory-prefix=C:/temp/VID_DOWNLOAD -A "*.avi" -R "*999999.avi" http://192.168.0.11%%i/sd/
)
Sometimes (I have not been able to identify why), the wget encounters a problem and must terminate. This generates a dialogue that requires user interaction.
It does not bother me if there is an error, since the script is launched automatically every 5 minutes and wget eventually works fine. The problem is that I manually have to intervene and acknowledge the error.
I don't have much information about the error - it shows up like this:
Would it be possible to get wget to fail silently?

How can I answer a command that needs input in Plink?

I run a command in Linux remote machine using plink (from batch file in Windows).
For example:
plink.exe -ssh root#IP -pw pass -m testCommands.txt >> uninstall.log
In testCommands.txt I have a command that perform uninstall of application,
the problem is that command of "uninstall" require an answer (y or n),
How can I send answer in addition to what I already send?
Here is the question I have:
[?7hAre you sure you want to completely remove "APPLICATION" and all of its components?
Yes [y, Enter], No [n]"
There are several options...
Use a -y or auto-confirm option on the command that removes the software, e.g.
pkg rm -yes somePackacge
Use a pipe to send the yes, so that the command you run in PLINK looks like
printf "Yes\n" | pkg rm some_package
or
yes | pkg rm some_package
Make the command that you run on the Linux machine be based on expect which can spawn your remove command, wait for a question and then send it a confirmation. Some expect examples here.

why is checking a URL failing when run through icinga?

I created my own command to check a specific URL
define command{
command_name check_url
command_line /usr/lib/nagios/plugins/check_http -f follow -H '$HOSTNAME$' -I '$HOSTADDRESS$' -u '$ARG1$'
}
If I run my command from the command line, it works:
/usr/lib/nagios/plugins/check_http -f follow -H www.example.com -u http://www.example.com/server-status
HTTP OK: HTTP/1.1 200 OK - 4826 bytes in 0.011 second response time |time=0.010625s;;;0.000000 size=4826B;;;0
But when run through Icinga, I'm getting
HTTP WARNING: HTTP/1.1 404 NOT FOUND - 314 bytes in 0.011 second response time
My guess is for check_http plugin for -u option you should provide the url appended after the server name not the whole url.
Ex.
/usr/lib/nagios/plugins/check_http -f follow -H www.example.com -u /server-status
Your manual test is not equivalent to your command definition.
The distinction with -H/-I is subtle, but very important.
When I have problems like this, where Icinga is abstracting exactly how it is executing the command, I find it helpful to find out precicely what Icinga is executing. I would accomplish this as follows:
Move check_http to a temporary location
# mv /usr/lib/nagios/plugins/check_http /usr/lib/nagios/plugins/check_http_actual
Make a bash script that Icinga will call instead of the actual check_http script
# vi /usr/lib/nagios/plugins/check_http
In that file, create this simple bash script, which simply echos the command line arguments it was called with, then exits:
#!/bin/bash
echo $#
Then of course, make that bash script executable:
# chmod +x /usr/lib/nagios/plugins/check_http
Now in Icinga, run the check_http command. At that point, the return status shown in the Icinga web interface will show exactly how Icinga is calling check_http. Seeing the raw command, it should be obvious as to what Icinga is doing wrong. Once you correct Icinga's mistake, you can simply move the original check_http script back into place:
# mv /usr/lib/nagios/plugins/{check_http_actual,check_http}

How do I enable FFMPEG logging and where can I find the FFMPEG log file?

I want to be able to log FFMPEG processes because I am trying to work out how long a minute of video takes to convert to help with capacity planning of my video encoding server. How do I enable logging and where is the log file saved. I have FFMPEG installed on a CentOS LAMP machine.
FFmpeg does not write to a specific log file, but rather sends its output to standard error. To capture that, you need to either
capture and parse it as it is generated
redirect standard error to a file and read that afterward the process is finished
Example for std error redirection:
ffmpeg -i myinput.avi {a-bunch-of-important-params} out.flv 2> /path/to/out.txt
Once the process is done, you can inspect out.txt.
It's a bit trickier to do the first option, but it is possible. (I've done it myself. So have others. Have a look around SO and the net for details.)
I found the below stuff in ffmpeg Docs. Hope this helps! :)
Reference: http://ffmpeg.org/ffmpeg.html#toc-Generic-options
‘-report’ Dump full command line and console output to a file named
program-YYYYMMDD-HHMMSS.log in the current directory. This file can be
useful for bug reports. It also implies -loglevel verbose.
Note: setting the environment variable FFREPORT to any value has the
same effect.
I find the answer.
1/First put in the presets, i have this example "Output format MPEG2 DVD HQ"
-vcodec mpeg2video -vstats_file MFRfile.txt -r 29.97 -s 352x480 -aspect 4:3 -b 4000k -mbd rd -trellis -mv0 -cmp 2 -subcmp 2 -acodec mp2 -ab 192k -ar 48000 -ac 2
If you want a report includes the commands -vstats_file MFRfile.txt into the presets like the example. this can make a report which it's ubicadet in the folder source of your file Source.
you can put any name if you want , i solved my problem "i write many times in this forum" reading a complete .docx about mpeg properties. finally i can do my progress bar reading this txt file generated.
Regards.
ffmpeg logs to stderr, and can log to a file with a different log-level from stderr. The -report command-line option doesn't give you control of the log file name or the log level, so setting the environment variable is preferable.
(-v is a synonym for -loglevel. Run ffmpeg -v help to see the levels. Run ffmpeg -h full | less to see EVERYTHING. Or consult the online docs, or their wiki pages like the h.264 encode guide).
#!/bin/bash
of=out.mkv
FFREPORT="level=32:file=$of.log" ffmpeg -v verbose -i src.mp4 -c:a copy -preset slower -c:v libx264 -crf 21 "$of"
That will trancode src.mp4 with x264, and set the log level for stderr to "verbose", and the log level for out.mkv.log to "status".
(AV_LOG_WARNING=24, AV_LOG_INFO=32, AV_LOG_VERBOSE=40, etc.). Support for this was added 2 years ago, so you need a non-ancient version of ffmpeg. (Always a good idea anyway, for security / bugfixes and speedups)
A few codecs, like -c:v libx265, write directly to stderr instead of using ffmpeg's logging infrastructure. So their log messages don't end up in the report file. I assume this is a bug / TODO-list item.
To log stderr, while still seeing it in a terminal, you can use tee(1).
If you use a log level that includes status line updates (the default -v info, or higher), they will be included in the log file, separated with ^M (carriage return aka \r). There's no log level that includes encoder stats (like SSIM) but not status-line updates, so the best option is probably to filter that stream.
If don't want to filter (e.g. so the fps / bitrate at each status-update interval is there in the file), you can use less -r to pass them through directly to your terminal so you can view the files cleanly. If you have .enc logs from several encodes that you want to flip through, less -r ++G *.enc works great. (++G means start at the end of the file, for all files). With single-key key bindings like . and , for next file and previous file, you can flip through some log files very nicely. (the default bindings are :n and :p).
If you do want to filter, sed 's/.*\r//' works perfectly for ffmpeg output. (In the general case, you need something like vt100.py, but not for just carriage returns). There are (at least) two ways to do this with tee + sed: tee to /dev/tty and pipe tee's output into sed, or use a process substitution to tee into a pipe to sed.
# pass stdout and stderr through to the terminal,
## and log a filtered version to a file (with only the last status-line update).
of="$1-x265.mkv"
ffmpeg -v info -i "$1" -c:a copy -c:v libx265 ... "$of" |& # pipe stdout and stderr
tee /dev/tty | sed 's/.*\r//' >> "$of.enc"
## or with process substitution where tee's arg will be something like /dev/fd/123
ffmpeg -v info -i "$1" -c:a copy -c:v libx265 ... "$of" |&
tee >(sed 's/.*\r//' >> "$of.enc")
For testing a few different encode parameters, you can make a function like this one that I used recently to test some stuff. I had it all on one line so I could easily up-arrow and edit it, but I'll un-obfuscate it here. (That's why there are ;s at the end of each line)
ffenc-testclip(){
# v should be set by the caller, to a vertical resolution. We scale to WxH, where W is a multiple of 8 (-vf scale=-8:$v)
db=0; # convenient to use shell vars to encode settings that you want to include in the filename and the ffmpeg cmdline
of=25s#21.15.${v}p.x265$pre.mkv;
[[ -e "$of.enc" ]]&&echo "$of.enc exists"&&return; # early-out if the file exists
# encode 25 seconds starting at 21m15s (or the keyframe before that)
nice -14 ffmpeg -ss $((21*60+15)) -i src.mp4 -t 25 -map 0 -metadata title= -color_primaries bt709 -color_trc bt709 -colorspace bt709 -sws_flags lanczos+print_info -c:a copy -c:v libx265 -b:v 1500k -vf scale=-8:$v -preset $pre -ssim 1 -x265-params ssim=1:cu-stats=1:deblock=$db:aq-mode=1:lookahead-slices=0 "$of" |&
tee /dev/tty | sed 's/.*\r//' >> "$of.enc";
}
# and use it with nested loops like this.
for pre in fast slow; do for v in 360 480 648 792;do ffenc-testclip ;done;done
less -r ++G *.enc # -r is useful if you didn't use sed
Note that it tests for existence of the output video file to avoid spewing extra garbage into the log file if it already exists. Even so, I used and append (>>) redirect.
It would be "cleaner" to write a shell function that took args instead of looking at shell variables, but this was convenient and easy to write for my own use. That's also why I saved space by not properly quoting all my variable expansions. ($v instead of "$v")
appears that if you add this to the command line:
-loglevel debug
or
-loglevel verbose
You get more verbose debugging output to the command line.
You can find more debugging info just simply adding the option -loglevel debug, full command will be
ffmpeg -i INPUT OUTPUT -loglevel debug -v verbose
You must declare the reportfile as variable for console.
Problem is all the Dokumentations you can find are not running so ..
I was give 1 day of my live to find the right way ....
Example: for batch/console
cmd.exe /K set FFREPORT=file='C:\ffmpeg\proto\test.log':level=32 && C:\ffmpeg\bin\ffmpeg.exe -loglevel warning -report -i inputfile f outputfile
Exemple Javascript:
var reortlogfile = "cmd.exe /K set FFREPORT=file='C:\ffmpeg\proto\" + filename + ".log':level=32 && C:\ffmpeg\bin\ffmpeg.exe" .......;
You can change the dir and filename how ever you want.
Frank from Berlin
If you just want to know how long it takes for the command to execute, you may consider using the time command. You for example use time ffmpeg -i myvideoofoneminute.aformat out.anotherformat

Resources