I'm encountering a strange problem when redirecting STDOUT and STDERR. The following works as expected:
$ gvim --version > /tmp/version.out
$ ls -l /tmp/version.out
-rw-r--r--. 1 blah blah 3419 Jun 27 17:28 /tmp/version.out
There are 3419 characters in the output file and when I look at the file, it contains what I expect.
However, it does not work as expected when I do the following:
$ gvim --version > /tmp/version.out 2> /tmp/version.err
$ ls -latr /tmp/version.*
-rw-r--r--. 1 blah blah 0 Jun 27 17:29 /tmp/version.out
-rw-r--r--. 1 blah blah 0 Jun 27 17:29 /tmp/version.err
Notice that both the .out and the .err files are zero length this time. I tried this with an ls command and it works as expected:
$ ls . /ZZZ > /tmp/ls.out 2> /tmp/ls.err
$ ls -l /tmp/ls.*
-rw-r--r--. 1 blah blah 50 Jun 27 17:45 /tmp/ls.err
-rw-r--r--. 1 blah blah 33 Jun 27 17:45 /tmp/ls.out
Here, the STDERR gets redirected properly:
$ cat /tmp/ls.err
ls: cannot access /ZZZ: No such file or directory
I did an strace on gvim --version and confirmed that it's trying to write the version info to STDOUT (fd 1). It shouldn't matter either way though since I'm trying to capture both STDOUT and STDERR.
What's going on here?
Congratulations, you just found a bug in gvim!
Correct procedure is to file a new issue on GitHub.
You should first try another variations of the bug, so that developers have the debugging easier.
For example, redirecting only STDERR also causes the error, because there was no output written. Also there was returned success (0), which is obviously an bug.
$ gvim --version 2> /tmp/version.err
$ echo $?
0
By only looking into the code one may search for the bug somewhere in version printing, or anywhere in generic --version argument processing, not being done by gtk.
To answer your question
What is going on?
It's a program error, made by developers of gvim and I would not recommend you to put effort into finding its root cause unless you are experienced with coding vim or if you want to learn, how vim works. In that case, your best shot is to fork the repo and after fixing it, submitting a pull request, so that everyone can benefit from your work.
The specific condition that triggers the bug seems to be when standard error is not a terminal. When I tried redirecting standard error to another terminal device, the --version message was still printed to standard output.
ek#Io:~$ gvim --version 2>/dev/null
ek#Io:~$ tty
/dev/pts/1
ek#Io:~$ who
ek tty7 2017-07-05 02:48 (:0)
ek pts/1 2017-07-10 09:10 (192.168.10.3)
ek pts/3 2017-07-10 09:23 (192.168.10.3)
ek#Io:~$ gvim --version 2>/dev/pts/3
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 24 2016 16:44:48)
....
Apparently Vim calls isatty(2) to help figure out if it should use a terminal at all. From a comment in gui.c:
Return TRUE if still starting up and there is no place to enter text.
For GTK and X11 we check if stderr is not a tty, which means we were (probably) started from the desktop. Also check stdin, "vim >& file"
does allow typing on stdin.
But the rest of that comment (i.e., the part I didn't highlight), and instances of isatty(2) throughout multiple files, make it not immediately obvious what ought to be changed.
Running grep -RF 'isatty(2)' on the source tree revealed that this is used in gui.c, message.c, and main.c. (That doesn't mean the bug is in all those files, of course.) You might also look at all the instances of isatty in the source code.
In any case, as jirislav says, this ought to be reported as a bug--even if a full explanation of the problem is not yet apparent. I am able to reproduce this with the current upstream sources (commit 163095f).
Related
I want every command ran from a bash script to be echoed with the custom prefix of ##[command]. This has a meaning when the script is run from Azure Pipelines.
For example, when running ls -l from such a script I would like to see something like this:
##[command]ls -l
total 20
-rw-r--r-- 1 mark mark 2447 Nov 14 23:56 1.txt
-rw-r--r-- 1 mark mark 1533 Nov 14 23:56 2.txt
-rw-r--r-- 1 mark mark 1545 Nov 14 23:56 3.txt
-rw-r--r-- 1 mark mark 6918 Nov 14 23:56 4.txt
The solution could be something automatic or some kind of a function, which could be invoked like this: run('ls -l').
Using a function means there would be a special step in every build job to ensure this function is defined in the .bashrc script, so that subsequent steps could see it. At least, this is what I think, not sure if bash steps load the .bashrc script at all.
Anyway, the solution should be applicable to multiple steps in an Azure Pipeline YAML without a lot of overhead.
I suggest to use with bash:
PS4="##[command]"; set -x
I'm trying to suppress some of the output from octave as per this post: https://stackoverflow.com/a/8303754/1033422:
oldpager = PAGER('/dev/null');
oldpso = page_screen_output(1);
oldpoi = page_output_immediately(1);
... do some stuff
PAGER(oldpager);
page_screen_output(oldpso);
page_output_immediately(oldpoi);
However, when I run my script, octave is displaying the error:
sh: /dev/null: Permission denied
Update:
$ ls -l /dev/null
crw-rw-rw- 1 root wheel 3, 2 24 Jan 19:07 /dev/null
The issue is that PAGER is expecting a program (such as less) and /dev/null is not a program.
Query or set the internal variable that specifies the program to use to display terminal output on your system.
Instead, what you could do would be to set PAGER such that it uses less but then pipes the output directly to /dev/null
PAGER('less > /dev/null')
I would lie to understand how logadm works.
So by looking at the online materials I wrote a small script which redirects a date into a log file and sleeps for 1 second. this will run in a infinite loop.
#!/usr/bin/bash
while true
do
echo `date` >>/var/tmp/temp.log
sleep 1
done
After this I had executed below commands:
logadm -w /var/tmp/temp.log -s 100b
logadm -V
My intention from above commands is log(/var/tmp/temp.log) should be rotated for every 100 bytes.
But after setting these , when I run the script in background, I see the log file is not rotated.
# ls -lrth /var/tmp/temp.log*
-rw-r--r-- 1 root root 7.2K Jun 15 08:56 /var/tmp/temp.log
#
As I understand, you have to call it to do work, e.g. from crontab or manually like logadm -c /var/tmp/temp.log (usually placecd in crontab)
Sidenode: you could simply write date >> /var/tmp/temp.log w/o echo.
This not how I would normally do this, plus I think you may have misunderstood the -w option.
The -w option updates /etc/logadm.conf with the parameters on the command line, and logadm is then run at 10 minutes past 3am (on the machine I checked).
I took your script and ran it, then ran:
"logadm -s 100b /var/tmp/temp.log"
and it worked fine. Give it a try! :-)
I installed bashdb on fedora 21 which uses bash 4.3 . I need to run using --debugger because I want $0 to be set correctly to the name of the script rather than bashdb.
bash --debugger my.bash
But the script is just executed, there is no debug session. On the other hand running:
bash --debugger my.bash ""
works fine.
What am I doing wrong?
This is a bug that I think was introduced in bash 4.3: Wed Feb 26 09:36:43 2014 -0500 Bash-4.3 distribution sources and documentation
The code added that causes this is:
if (debugging_mode && locally_skip_execution == 0 && running_setuid == 0 && dollar_vars[1])
start_debugger ();
I have posted a bug report on this. See http://lists.gnu.org/archive/html/bug-bash/2015-04/msg00183.html
The short story in the above thread is that although bash versions 4.3 up to 4.3.33 have this bug, in the next release after 4.3.33 (sometime after April 2015), this bug will be fixed.
When you use bash --debugger, the debugger has to be installed in the location that bash expects. Although the configure script tries to figure this out, many times it gets this wrong. To see where bash thinks the debugger should be installed, run:
strings /bin/bash | grep bashdb
On Ubuntu, the answer I got was: /usr/share/bashdb/bashdb-main.inc. So bashdb is expected to be installed in /usr/share/bashdb. Using this, then run configure like this:
/bin/bash ./configure -with-bashdb-main.inc=/usr/share/bashdb/bashdb-main.inc
How can i read the content of a xterm or terminal, only by knowing its device number?
Similar to moving the mouse over the text.
Redirecting or cloning the terminal output to a file would be an option too, as long it could be done without interacting with commands executed in this terminal.
So nothing like 'command > myfile'.
Or is the only way to solve this a print screen with ocr or simulating mouse moves and clicks?
Edit: I m looking for a solution that reads the content regardless of his origin, p.e. 'echo "to tty" > /dev/pts/1'
The script command may work for you.
"Script makes a typescript of everything printed on your terminal. It is useful for students who need a hardcopy record of an interactive session as proof of an assignment, as the typescript file can be printed out later" - man script
You can even pass script as command when invoking xterm with -e:
ubuntu#ubuntu:~$ xterm -e script
ubuntu#ubuntu:~$ # A new xterm is started. uname is run, then exit
ubuntu#ubuntu:~$ # The output is captured to a file called typescript, by default:
ubuntu#ubuntu:~$ cat typescript
Script started on Tue 19 Nov 2013 06:00:07 PM PST
ubuntu#ubuntu:~$ uname
Linux
ubuntu#ubuntu:~$ exit
exit
Script done on Tue 19 Nov 2013 06:00:13 PM PST
ubuntu#ubuntu:~$