How to know, when to use 1> and 2>

In cron I've put line:
Code:
echo "HEEEELOOO!!" && portsnap fetch update > /dev/null && echo "HEEEELOOO!!"

So, what I wanted to achieve:
If all went without errors, then don't pester me with STDOUT output emails
That is..., IF error occurs with portsnap, THEN email me STDERR.

And here we come to unlogic behaviour.
Line above, in cron will fail and only first echo "HEEEELOOO!!" will appear in mail as fail occur at second(portsnap) part
But I get no reason/explanation, becuse STDERR is empty and portsnap's error msg ended up in STDOUT, which I've set to go to hell(/dev/null), assuming it would contain repetitive pestering content

Removing ' > /dev/null', part exposed:
portsnap fetch should not be run non-interactively.
Run portsnap cron instead.

Now THAT was supposed to go in STDERR!


Soon I will start to code scripts that control OS, so I need to know, this.
ATM, look very unlogic to me.
 
It really depends on the app. If it is coded to output a message to stdout, it will output there. If it is coded to output to stderr, it will output there.

portsnap was coded to output that message to stdout. I don't know of a design standard that defines when/where the two should be used that is well followed by programmers.

In other words, YMMV.
 
You got to be kidding me right?!?
Well then, that is a CHAOS...
And we want order!

I mean..., this totally defeats the purpose of existance of both STDOUT and STDERR.
Then we should just replace them with "1 out" :P
 
Seeker said:
I mean..., this totally defeats the purpose of existance of both STDOUT and STDERR.
Then we should just replace them with "1 out" :P
Well, you could try contact the portsnap author. Go ahead and submit a patch against portsnap. It's a dead simple fix. Lines 1002-1005 in /usr/src/usr.sbin/portsnap/portsnap/portsnap.sh.
 
I have to agree, errors should be printed to stderr not stdout. It's probably relatively easy to modify portsnap to do this.

To fix this issue you could just write a wrapper script that runs portsnap and checks it's return code.
 
You should handle stdout and stderr both as possible outputs for error. Pipe stderr to stdout, then handle return value of executed program (like portsnap) if program returned other than 0 then process stdout as error description or/and handle return value via perror(1).
 
I am talking about global scope, of this issue, that is active for ALL application.
No mater are they from base system, as portsnap is(!), or from apps, installed from ports.

I can't write patch for all of them.
 
Yes thats why like I said you should handle both stdout and stderr as possible error output. Generally most of apps handle return values correctly so scripts depending on them rarely fail.
 
Isn't this the same when starting an application from terminal and warnings and errors are printed to the (Sdtout) terminal?

I always have to start an application with this addition:

in csh:

Code:
>& /dev/null &

in sh:

Code:
2> /dev/null &

Then all the output is gone.
 
Ok, ok, that is when I start do scripting.
Right now I use form of, from example in cron:
Code:
comm[B]A[/B] && comm[B]B[/B] && comm[B]C[/B]
One that fails, stops further execution in chain...
And THEN I wana error message

So if I force 2>&1 I can't get rid of pestering effect, when all is well
 
Seeker said:
Ok, ok, that is when I start do scripting.
Right now I use form of, from example in cron:
Code:
comm[B]A[/B] && comm[B]B[/B] && comm[B]C[/B]
One that fails, stops further execution in chain...
And THEN I wana error message

So if I force 2>&1 I can't get rid of pestering effect, when all is well

Your script should cache output as a log for later reference by your script's procedures or user itself. So you end up with 0 output from running apps in the terminal. And then parse the needed output from the log when needed.
 
expl said:
Your script should cache output as a log for later reference by your script's procedures or user itself. So you end up with 0 output from running apps in the terminal. And then parse the needed output from the log when needed.

But then, I won't know WHEN is that needing time!
Simply because in both cases, no matter if error occurs or not, everything goes into logs.

So I am left to the: "Something doesn't feel right" effect..., so let me check logs, maybe I find something useful, down there.

That sucks! :P
 
Return values indicate when you need to check the log. If app executed fine it should return 0, if not it will return something else usually an error code.
 
expl said:
Return values indicate when you need to check the log. If app executed fine it should return 0, if not it will return something else usually an error code.
And(second time), that is useful, when I start do scripting.
Now, this is chained cmd line, in crontab for cron to execute, of type:
Code:
commA && commB && commC
 
expl said:
Well there are no easy solutions.
There are!
It is just, that those app. devs, are irresponsible cattle(that has to be tamed), thus making this mess, with no easy solutions!
 
What everyone is saying is that you should not be writing "appA && appB && appC" directly in the crontab. Instead, just use /path/to/some/script. Then write a wrapper script that correctly calls each app, saves their output somewhere, checks their return code, and either outputs nothing (return code is 0) or processes the output (return code is non-0).

Which is pretty much what everyone does. No one executes more than simple commands directly in crontab.
 
Seeker said:
There are!
It is just, that those app. devs, are irresponsible cattle(that has to be tamed), thus making this mess, with no easy solutions!
There are no guarantees in life. Anyone older than 12 should know this.

As for a "simple" solution, maybe this is what you're looking for?

Code:
(commA >/tmp/blah 2>&1 || ( cat /tmp/blah && false) ) && (commB >/tmp/blah 2>&1 || cat /tmp/blah )

When I said simple, I actually meant messy as hell.
 
aragon said:
There are no guarantees in life. Anyone older than 12 should know this.

As for a "simple" solution, maybe this is what you're looking for?

Code:
(commA >/tmp/blah 2>&1 || ( cat /tmp/blah && false) ) && (commB >/tmp/blah 2>&1 || cat /tmp/blah )

When I said simple, I actually meant messy as hell.

Uhuh. What about this one?
Code:
( commA && commB && commC ) > /tmp/log.$$ 2>&1 && rm /tmp/log.$$ || cat /tmp/log.$$
 
That is simpler, but I think it will mix outputs together, ie. if commB fails and commA produced output (without failing), commA and commB outputs would be mixed.

Maybe some demarcation echos can be added:

Code:
( echo commA starting... && commA && echo commB starting... && commB && echo commC starting... && commC ) > /tmp/log.$$ 2>&1 && rm /tmp/log.$$ || cat /tmp/log.$$
 
Like phoenix said: if you need more than one command started from cron, script the whole thing, and run it through [cmd=]sh -x(v)[/cmd] a few times to see if you have everything right. Cron is not designed as a fully functional shell, it is just a jumping board to launch external programs or scripts.
 
Ok, guys thanks!
I get it. Scripting is a way to go...

Now, I put in cron line: /path/to/script

It is intended to be executed by user and by cron.
Here I need some sh scripting, in a way that script can recognize it has been executed by a cron in the name of a root:
Code:
echo "HEEEELOOO!!" && portsnap [B]fetch[/B] update > /dev/null && echo "HEEEELOOO!!"
becomes:
Code:
echo "HEEEELOOO!!" && portsnap [B]cron[/B] update > /dev/null && echo "HEEEELOOO!!"
So that in bold will be some variable in /path/to/script.

Now I need code snippet, that detects if cron is executing /path/to/script, possibly in a same way portsnap detects it.(It will halt if invoked with fetch, instead of cron arg)
 
Just add a command-line variable in cron, and import it into the script.

Start from cron like:

Code:
/path/to/script fromcron

In script:

Code:
if [ $1 = "fromcron" ]
then
var=cron
else
var=fetch
fi

portsnap $var update

Or use/adjust my script ;)
 
Back
Top