On Linux, the following cd works fine so cds into tmp:

/ # cd /tmp
tmp # 

But this does not work (stays at root, nothing appears in /var/log/messages). Why not?

/ # cd /tmp 2>&1 | /usr/bin/logger -t Test
/ #

I tried with stripping off this stderr redirect but that also did not work.

My goal is to redirect all output of my script to syslog, so also if I try to CD in a directory which does not exist/permission denied/etc. Why is it not working and how to get this working?

A normal echo does print to syslog so that does work:

echo Test | /usr/bin/logger -t Test

1 Answer 1


A pipe executes the producer (left-hand) process and the consumer (right-hand) process in parallel. Since there are two processes in parallel, at least one of them needs to be a child process of the main shell process, possibly both.

Most shells execute both sides of the pipe in subprocesses. ATT ksh and zsh execute the right-hand side in the original process.

The cd command changes the current shell process's current directory, so it needs to be a builtin. Since the left-hand side of the pipe is executed in a subshell (a subprocess that's forked from the shell process executing the script), the cd command only takes effect in the subshell. It works, but since the subshell exits immediately afterwards, it doesn't do anything useful. You can observe it with

{ cd /tmp; echo -n "left-hand side: "; pwd; } | 
{ cd /usr; echo -n "right-hand side: "; pwd; }
echo -n "parent: "; pwd

To log the output from your script, make a single pipeline that applies to your whole script.

main () {
  … # whole script goes here
main | logger

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .