l i n u x - u s e r s - g r o u p - o f - d a v i s
L U G O D
 
Next Meeting:
August 5: Social gathering
Next Installfest:
TBD
Latest News:
Jul. 4: July, August and September: Security, Photography and Programming for Kids
Page last updated:
2002 May 29 14:41

The following is an archive of a post made to our 'vox-tech mailing list' by one of its subscribers.

Report this post as spam:

(Enter your email address)
Re: [vox-tech] quick, stupid bash question
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [vox-tech] quick, stupid bash question



On Wed, May 29, 2002 at 03:18:08PM -0400, msimons@moria.simons-clan.com wrote:
> On Wed, May 29, 2002 at 11:29:29AM -0700, Peter Jay Salzman wrote:
> > begin nbs <nbs@sonic.net> 
> > >      strace lsof 2>&1 1> /dev/null | grep
> >  
> > ok, haven't tried this, but this looks to me like:
> > 
> > put stderr into stdout
> > redirect stdout (and therefore stderr) into /dev/null
> > pipe stdout (which should be null) to grep.
> 
>   The order of operation of file operators is right to left.  

On Wed, May 29, 2002 at 12:32:45PM -0700, Shawn P. Neugebauer wrote:
> The order of redirects is left to right.

  Based on Shawn's comment I've done some tests and operation is very
much left to right like he says.  Now I have a better understanding of 
how dup2 works... but I hope I really don't need to use this anytime 
soon.


>  ( strace ls -R / 2>&1 1>&3 | grep open; ) 3>&1

  Since I'm revising most of this email I would now recommend the 
following...

  ( exec 3>&1 4>&2; strace ls -R / 2>&1 1>&3 | grep open 1>&4 ) 

  It does a similar thing to the one above... but has the nicer property of 
after the ')' the grepped output from strace is still going to stderr and
ls going to stdout, which the first version doesn't do (they are both going
to stdout).  This way you can redirect view them correctly or split them
into other places later.


> > >      strace lsof 2>&1 1> /dev/null | grep
>
>   So the first operation "| grep" spawns a copy of grep on the 
> stdout of a future output of a new pipe.  The second "1> /dev/null" 
> takes stdout and throws it away.  The third "2>&1" takes stderr and 
> redirects it to stdout.

In the parent
============
A - '|'
  The first thing that happens is a pipe (see pipe(2) manpage) because '|'
appears in the command.  This call creates two fds (3 and 4) which are 
attached together... and is to handle communication between strace
and grep.
============

Fork child 1
============
A -  '|'
  The child closes fd 3, which is for pipe reading.  invokes dup2(4, 1) which
attaches the fd 1 to the output channel on the pipe and closes fd 4.

B - '2>&1'
  Invoke the dup2(2, 1) system call, which closes the old stderr 
(which was going to the user's terminal) and makes fd 2 (point at the same 
place as stdout, which in this case can be thought of as the user's terminal).

C - '1> /dev/null'
  Open /dev/null for writing, then dup2(X, 1) which attaches a new 'stdout' 
to the /dev/null file, and close(X).

D - then exec the command "strace ..."
============

Back in the parent
============
A - the parent closes fd 4, since it is meant for writing by child 1.

E - the parent forks another child

A - the parent closes fd 3, since it is meant for reading by child 2.

(there appears to be a bug in bash that the parent of a pipe creation
 closes both the input and output channels twice of a pipe twice).
============

Fork child 2
============
F - Call dup2(3, 0) which attaches the input pipe fd 3 to this 
    processes stdin.

G - then exec the command "grep ..."
============


  Here are the actual calls captured by strace... the letters in the
first column are supposed to help understand which step above is 
being processed at the time.

in one window
=====
msimons@star:~$ echo $$
693
msimons@star:~$ strace ls / 2>&1 1> /dev/null | grep open
=====

in another window
====
msimons@star:~$ strace -f -p 693 -e execve,close,dup2,open,fork
A [pid   683] pipe([3, 4])                            = 0
  [pid   693] fork()                      = 31806

A [pid 31806] close(3)                    = 0
A [pid 31806] dup2(4, 1)                  = 1
A [pid 31806] close(4)                    = 0
B [pid 31806] dup2(1, 2)                  = 2
C [pid 31806] open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
C [pid 31806] dup2(3, 1)                  = 1
C [pid 31806] close(3)                    = 0
D [pid 31806] execve("/usr/bin/strace", ["strace", "ls", "/"], [/* 27 vars */]) =  0

A [pid   693] close(4)                    = 0
A* [pid   693] close(4)                    = -1 EBADF (Bad file descriptor)
E [pid   693] fork()                      = 31808
A [pid   693] close(3)                    = 0
A* [pid   693] close(3)                    = -1 EBADF (Bad file descriptor)

F [pid 31808] dup2(3, 0)                  = 0
F [pid 31808] close(3)                    = 0
G [pid 31808] execve("/bin/grep", ["grep", "open"], [/* 27 vars */]) = 0
====


>  ( strace ls -R / 2>&1 1>&3 | grep open; ) 3>&1

  here is a correct breakdown of the command-line above in order of 
operation...
=========
- fork a child_A for '3>&1'
- in child_A
  - dup2(1, 3) for '3>&1'
  - create pipe for '|'
  - fork child_B for for 'strace'
  - close pipe out channel (twice) for '|'
  - fork child_C for grep
  - close pipe in channel (twice) for '|'

- in child_B (strace)
  - close pipe input channel for '|'
  - attach stdout to pipe output channel, 
    then close pipe out channel fd 5 for '|'
  - attach stderr to stdout for '2>&1'
  - attach stdout to fd 3 for '3>&1'
  - exec strace...

- in child_C (grep)
  - attach stdin to pipe input channel, 
    then close pipe in channel fd 4 for '|'
  - exec grep
=========
_______________________________________________
vox-tech mailing list
vox-tech@lists.lugod.org
http://lists.lugod.org/mailman/listinfo/vox-tech



LinkedIn
LUGOD Group on LinkedIn
Sign up for LUGOD event announcements
Your email address:
facebook
LUGOD Group on Facebook
'Like' LUGOD on Facebook:

Hosting provided by:
Sunset Systems
Sunset Systems offers preconfigured Linux systems, remote system administration and custom software development.

LUGOD: Linux Users' Group of Davis
PO Box 2082, Davis, CA 95617
Contact Us

LUGOD is a 501(c)7 non-profit organization
based in Davis, California
and serving the Sacramento area.
"Linux" is a trademark of Linus Torvalds.

Sponsored in part by:
EDGE Tech Corp.
For donating some give-aways for our meetings.