For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > February 2008 > how to redirect stderr,stdin to a file from shell









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author how to redirect stderr,stdin to a file from shell
sinbad

2008-02-15, 4:30 am

hi,
Is there any way to redirect stderr,stdin to a file from shell
command.pls let me know.

thanks
sinbad
Logan Shaw

2008-02-15, 4:30 am

sinbad wrote:
> Is there any way to redirect stderr,stdin to a file from shell
> command.pls let me know.


Yeah. The manual page explains how to do it.

In sh/ksh/bash, you would do this:

foo > file-to-contain-stdout

or this:

foo 2> file-to-contain-stderr

Directing stdin to a file sounds like it wouldn't be very
useful, so I haven't really considered how to do that before.

- Logan
lak

2008-02-15, 4:30 am

On Feb 15, 10:10 am, sinbad <sinbad.sin...@gmail.com> wrote:
> hi,
> Is there any way to redirect stderr,stdin to a file from shell
> command.pls let me know.
>
> thanks
> sinbad


If you want to redirect both error and stdout to a file then do the
following
command 1>filename 2>&1
Johannes Bauer

2008-02-15, 8:12 am

Logan Shaw schrieb:

> Directing stdin to a file sounds like it wouldn't be very
> useful, so I haven't really considered how to do that before.


Huh? Are you kidding?

$ wc -l < freibier.tar.bz2

It is *extremely* useful for applications which do not provide direct
file access (yeah, I know, wc does).

Regards,
Johannes

--
"PS: Ein Realname wäre nett. Ich selbst nutze nur keinen, weil mich die
meisten hier bereits mit Namen kennen." -- Markus Gronotte aka Makus /
Kosst Amojan / maqqusz / Mr. G / Ferdinand Simpson / Quartillia
Rosenberg in dse <45608268$0$5719$9b4e6d93@newsspool3.arcor-online.net>
Henry Townsend

2008-02-15, 7:17 pm

Johannes Bauer wrote:
> Logan Shaw schrieb:
>
>
> Huh? Are you kidding?
>
> $ wc -l < freibier.tar.bz2
>
> It is *extremely* useful for applications which do not provide direct
> file access (yeah, I know, wc does).


I think the distinction he was making is *to* vs *from*. E.g.

$ wc 0> foo

HT
Stephane Chazelas

2008-02-15, 7:17 pm

On Fri, 15 Feb 2008 09:32:47 -0500, Henry Townsend wrote:
> Johannes Bauer wrote:
>
> I think the distinction he was making is *to* vs *from*. E.g.
>
> $ wc 0> foo

[...]

But wc *reads* from its stdin like most sensible applications
do, it doesn't write to it.

In, the above, wc will fail to do its job as it will try to read
from a file descriptor open for writing only, and the "foo" file
will remain empty as wc won't write anything on its fd 0.

--
Stephane
Joe.pHsiao@gmail.com

2008-02-15, 7:17 pm

Hello,

I am having the same question, so I clicked this thread.

I am implementing a shell for school's project.
The shell needs to read a resource file at the beginning of execution.
So I need to redirect its STDIN to a file descriptor to execute
commands in a resources file, and then restore STDIN back to the
keyboard for user input.

Here is what I am doing.

int keep = dup( 0 );
int fd = open( ".resource", ... );
dup2( fd, 0 );
close( fd );

// parse and execute commands

dup2( keep, 0 );
close( keep );

while( 1 ){
cout << hostname << "%";
// process commands from keyboard
}

The problem is after I add the part to handle a resource file, the
hostname% prompt doesn't show up.
The shell is still accepting input from keyboard and output to the
monitor as usual. Only the hostname% disappeared.
The output is like:

======
joe.Desktop%> ./myshell <-- execute myshell

*result output from resource file

<-- blank here, waiting for keyboard input ( hostname% should show
up here. )
=======

if I input "ls" command, it would be like

=======
ls <-- input from keyboard, press enter
hostname%
file1.c file2.c file3.c file4.c file5.c <-- result of
"ls"
<-- blank here, waiting for keyboard input ( hostname% should show
up here. )
=======


The weird thing is if hostname is output through "cerr", it's back to
normal.
hostname% is waiting there for users to input.
Obvious the problem is from the code which handles the resource file.
But it didn't touch STDOUT or STDERR.
Is there anything I am doing wrong?
Henry Townsend

2008-02-15, 7:17 pm

Stephane Chazelas wrote:
> On Fri, 15 Feb 2008 09:32:47 -0500, Henry Townsend wrote:
> [...]
>
> But wc *reads* from its stdin like most sensible applications
> do, it doesn't write to it.


Right, which is why the construct above is not useful. I feel I am in a
maze of twisty passages, all alike ....

HT
Logan Shaw

2008-02-16, 4:28 am

Henry Townsend wrote:
> Stephane Chazelas wrote:
>
> Right, which is why the construct above is not useful. I feel I am in a
> maze of twisty passages, all alike ....


Ooh, I'm wrong. It can be useful. Consider:

stty 0> $OTHER_TERMINAL

This will make stty print info about $OTHER_TERMINAL. It doesn't
matter that stdin is being redirected *to* some other file because
in this case stty isn't bothering to read or write to stdin; it's
just doing an ioctl.

Now, if I ever find myself in a situation where I have permission
to write to some terminal but not read from it, and I need to know
the terminal settings, them I'm all set. :-)

- Logan
William Pursell

2008-02-16, 8:11 am

On Feb 15, 6:55 pm, Joe.pHs...@gmail.com wrote:

> The shell needs to read a resource file at the beginning of execution.
> So I need to redirect its STDIN to a file descriptor to execute
> commands in a resources file, and then restore STDIN back to the
> keyboard for user input.


Why do you need to read the resource file on stdin? Why
not just read it on its own fd?

> Here is what I am doing.
>
> int keep = dup( 0 );
> int fd = open( ".resource", ... );
> dup2( fd, 0 );


I'm assuming you meant dup2( fd, STDIN_FILENO )
as opposed to, say, dup2( fd, FALSE) or
dup2( fd, ELFCLASSNONE) or dup2( fd, SEEK_SET )
(Magic numbers are BAD, even when they seem
trivial.)

> close( fd );
>
> // parse and execute commands
>
> dup2( keep, 0 );
> close( keep );
>
> while( 1 ){
> cout << hostname << "%";
> // process commands from keyboard
>
> }
>
> The problem is after I add the part to handle a resource file, the
> hostname% prompt doesn't show up.


Does it show up without the resource file handling? I'm
surprised that it does, without a flush here.

> The weird thing is if hostname is output through "cerr", it's back to
> normal.


Because stderr is unbuffered by default, the flush isn't needed.

> Obvious the problem is from the code which handles the resource file.
> But it didn't touch STDOUT or STDERR.
> Is there anything I am doing wrong?


You monkeyed with the file descriptors underlying the FILE *
stdin, which is generally a bad idea. It would be safer
to fclose( stdin ) and then use freopen(), but in your
case I don't see why you are trying to read the resource
file from stdin at all.

Joe.pHsiao@gmail.com

2008-02-16, 7:22 pm

Hi William,

Thanks for the reply.

> Why do you need to read the resource file on stdin? Why
> not just read it on its own fd?


Since those commands are in a file, I want to fed them to the program
as input from the keyboard.
For example, "wc < abc.data" would feed wc the data in abc.data.
A shell also gets input from keyboard, so I keep the old file
descriptor, which is pointed to keyboard ( or Terminal ), in STDIN,
and then restore it back after the data is read and executed in the
file.

What do you mean "read it on its own fd?"


> I'm assuming you meant dup2( fd, STDIN_FILENO )
> as opposed to, say, dup2( fd, FALSE) or
> dup2( fd, ELFCLASSNONE) or dup2( fd, SEEK_SET )
> (Magic numbers are BAD, even when they seem
> trivial.)


I changed all 0's to STDIN_FILENO, the result didn't change.

> You monkeyed with the file descriptors underlying the FILE *
> stdin, which is generally a bad idea. It would be safer
> to fclose( stdin ) and then use freopen(), but in your
> case I don't see why you are trying to read the resource
> file from stdin at all.


Since this is a school project, I am supposed to deal with underlying
file descriptors.
I am using open(), not fopen(), so I shouldn't use fclose() either.
William Pursell

2008-02-16, 7:22 pm

On Feb 16, 3:35 pm, Joe.pHs...@gmail.com wrote:

>
> Since those commands are in a file, I want to fed them to the program
> as input from the keyboard.
> For example, "wc < abc.data" would feed wc the data in abc.data.
> A shell also gets input from keyboard, so I keep the old file
> descriptor, which is pointed to keyboard ( or Terminal ), in STDIN,
> and then restore it back after the data is read and executed in the
> file.
>
> What do you mean "read it on its own fd?"


I mean skip the dup()ing. Just open the resource file
and read it:
fd = open("resource",...)
read(fd,...)
....
close(fd);

I don't see how anything is gained by forcing fd to
a specific value.

>
> I changed all 0's to STDIN_FILENO, the result didn't change.


No, it won't change the performance, just the readability
and maintainability.

>
>
> Since this is a school project, I am supposed to deal with underlying
> file descriptors.
> I am using open(), not fopen(), so I shouldn't use fclose() either.


You should not use fclose() on any file descriptor, but
there is a difference between using a file descriptor and "using
the underlying file descriptor". When you open() a file and
get a file descriptor, it is just a file descriptor. If you
then call fdopen() to get a FILE *, then the fd becomes
the underlying file descriptor of the FILE *, and you should use one
or the other, but not both. For example, consider what
happens in the following:


$ cat a.c
#include <stdlib.h>
#include <stdio.h>

#define LEN 15

int
main( int argc, char **argv )
{
int fd;
ssize_t rc;
char a[ LEN + 1 ];
char b[ LEN + 1 ];

/* SAMPLE OF BAD PRACTICE */
a[ LEN ] = b[ LEN ] = '\0';
fd = fileno( stdin );
fread( b, sizeof *b, LEN, stdin );
printf( "b = %s\n\n", b );
rc = read( fd, a, LEN );
printf( "rc = %u, a = %s\n\n", (unsigned)rc, a );
fread( b, sizeof *b, LEN, stdin );
printf( "b = %s\n", b );

return EXIT_SUCCESS;
}

$ gcc a.c && ./a.out < /usr/share/dict/words
b =
A
A's
AOL
AOL'

rc = 15, a = n
Alston's
Alta

b = s
Aachen
Aachen

As you can see, the read() on the underlying fd read
data "out of order". The first fread() read bytes 0-4095
and put bytes 0-14 in b, then read() read bytes 4096-4110.
The next call to fread() didn't read any new data, but just
put the previously read bytes 15-29 in b.

Working with both the FILE * and the underlying fd is
bad, because the stdio routines expect to have
control over the fd. I don't know exactly how these
things apply to cin and cout, but the principal is
undoubtedly the same.
Barry Margolin

2008-02-16, 7:22 pm

In article <47b68771$0$1101$4c368faf@roadrunner.com>,
Logan Shaw <lshaw-usenet@austin.rr.com> wrote:

> Ooh, I'm wrong. It can be useful. Consider:
>
> stty 0> $OTHER_TERMINAL
>
> This will make stty print info about $OTHER_TERMINAL.


So will

stty < $OTHER_TERMINAL

So what's the benefit of opening the other terminal for output?

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Logan Shaw

2008-02-20, 4:47 am

Barry Margolin wrote:
> In article <47b68771$0$1101$4c368faf@roadrunner.com>,
> Logan Shaw <lshaw-usenet@austin.rr.com> wrote:
>
>
> So will
>
> stty < $OTHER_TERMINAL
>
> So what's the benefit of opening the other terminal for output?


The benefit is that sometimes other terminals are writable but
not readable. At least on the system where I'm logged in right
now, I get this:

$ ls -l $(tty)
crw--w---- 1 logan tty 136, 1 2008-02-19 22:30 /dev/pts/1
$

Note the group permissions. A user who is a member of the tty
group could successfully do "stty 0> /dev/pts/1" but they would
get a permissions error doing "stty < /dev/pts/1".

Of course, the benefit is soooooo tiny, it's fairly silly to
talk about, but nevertheless, this *is* an example of a time
when "0>" allows you to do something that there is no other
easy way to do. :-)

- Logan
Joe.pHsiao@gmail.com

2008-02-21, 7:13 pm

On Feb 16, 2:21 pm, William Pursell <bill.purs...@gmail.com> wrote:
> On Feb 16, 3:35 pm, Joe.pHs...@gmail.com wrote:
>
>
>
>
> I mean skip the dup()ing. Just open the resource file
> and read it:
> fd = open("resource",...)
> read(fd,...)
> ...
> close(fd);


That's a great idea! No I/O re-direction is involved!
I think this will work.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2010 codecomments.com