Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Jun 2013 16:11:39 +0000
From:      "Teske, Devin" <Devin.Teske@fisglobal.com>
To:        Alexander Yerenkow <yerenkow@gmail.com>
Cc:        FreeBSD Hackers <freebsd-hackers@freebsd.org>, Devin Teske <dteske@freebsd.org>
Subject:   Re: Shell variables containing output redirects
Message-ID:  <13CA24D6AB415D428143D44749F57D7201F98E98@ltcfiswmsgmb21>
In-Reply-To: <13CA24D6AB415D428143D44749F57D7201F98E32@ltcfiswmsgmb21>
References:  <CAPJF9wm%2BeW-Ch99E6CZrGPcFt7hepn8y_m3fvLWTFp8PFXEt7Q@mail.gmail.com> <13CA24D6AB415D428143D44749F57D7201F98E32@ltcfiswmsgmb21>

next in thread | previous in thread | raw e-mail | index | archive | help

On Jun 20, 2013, at 9:04 AM, Teske, Devin wrote:

>=20
> On Jun 20, 2013, at 7:57 AM, Alexander Yerenkow wrote:
>=20
>> Hello all!
>>=20
>> I have a problem with port JBoss72, which tries to behave as long-standi=
ng
>> port jboss5:
>>=20
>> http://svnweb.freebsd.org/ports/head/java/jboss5/files/jboss5.in?revisio=
n=3D302141&view=3Dmarkup
>>=20
>>=20
>>=20
>> In rc run script there is such line:
>>=20
>> %%APP_SHORTNAME%%_logging=3D"${%%APP_SHORTNAME%%_logging:-">>
>> ${%%APP_SHORTNAME%%_logdir}/stdout.log 2>>
>> ${%%APP_SHORTNAME%%_logdir}/stderr.log"}"
>>=20
>> Which provides way to overwrite default log location in /etc/rc.conf.
>>=20
>> But this not working at all, all these redirects treated as simple
>> parameters for run script.
>>=20
>> I made small test, to show my problem:
>>=20
>> #!/bin/sh
>>=20
>> logfile=3D"supposed-to-be.log"
>> log=3D">> ${logfile}"
>> echo "a1" >> ${logfile}
>> echo "a2" ${log}
>> cmd=3D"echo \"a3\" ${log}"
>> echo $cmd
>> $cmd
>> more ${logfile}
>>=20
>> Here's execution output:
>>=20
>> # ./t1.sh
>> a2 >> supposed-to-be.log
>> echo "a3" >> supposed-to-be.log
>> "a3" >> supposed-to-be.log
>> a1
>>=20
>> 1. My question is - Which are correct way to specify such redirects to be
>> overridden?
>>=20
>=20
> If you must have a conditional redirect in the above manner (in which the=
 redirect syntax is part of a variable):
>=20
> to_foofile=3D">> foofile"
> eval echo \"a1\" $to_foofile
>=20
> The shell will do a first-pass on the arguments, so what "eval" sees as a=
rguments are:
>=20
> echo "a1" >> foofile
>=20
> And thus, eval does what it does best=85 evaluates the expressions as a s=
et of shell statements.
>=20
> NOTE: The rc script probably assumed bash and was ported from another sys=
tem where /bin/sh was indeed bash (but in FreeBSD, /bin/sh is not bash and =
is much more strict in adhering to POSIX standards).
>=20
> However, I can't in all earnest recommend that approach as a method of co=
nditional logging when there are so many better solutions.
>=20
> Here's one of my favorites for quick-and-dirty conditional logging:
>=20
> =3D=3D=3D
>=20
> #!/bin/sh
>=20
> if : some condition to enable debugging; then
> 	exec 3>>/tmp/log.stdout 4>>/tmp/log.stderr
> else
> 	exec 3>&1 4>&2
> fi
>=20
> echo "a1" 1>&3 2>&4
> 	# "a1" ends up in /tmp/log.stdout
>=20
> ls /nosuchfile 1>&3 2>&4
> 	# You get in /tmp/log.stderr: "ls: /nosuchfile: No such file or director=
y"
>=20
> =3D=3D=3D
>=20

Yeah=85 don't do that=85 the moment I hit send, it dawned on me that the ex=
tra file-descriptor (however cute), is entire unnecessary=85

=3D=3D=3D

#!/bin/sh
if : some condition to enable debugging; then
	exec 1>>/tmp/log.stdout 2>>/tmp/log.stderr
fi
echo d1
	# if debugging, goes to /tmp/log.stdout
	# if no debugging, goes to console
ls /nosuchfile
	# if debugging, an error goes to /tmp/log.stderr
	# if no debugging, error goes to console

=3D=3D=3D



> So rather than having to prefix "eval" to every command *and* escape all =
the quotes and expansions=85 the above instead changes from (old) attemptin=
g to use a conditional redirect syntax (by way of $logging variable) to (ne=
w/above) having every command redirect stdout/stderr but having the destina=
tions of the redirect change based on some pre-condition.
>=20
>=20
>=20
>> 2. tomcat6.in, rubyrep.in, tclhttpd.in, geoserver.in, and many more rc
>> scripts from ports are using something like this:
>>=20
>> log_args=3D">> ${tclhttpd_stdout_log} 2>> ${tclhttpd_stderr_log} "
>>=20
>> and after that use $log_args.
>>=20
>> Are they silently broken, or am I missing something?
>>=20
>=20
> I would call that broken if the invocation line at the top of the script =
is #!/bin/sh (it may not be broken if you instead see something like "#!/us=
r/bin/env bash").
>=20
>=20
>=20
>=20
>> 3. Should I build up $cmd, and run
>> eval "$cmd" - would this be nice ro dirty hack?
>>=20
>=20
> Nah=85 just go through and replace "$log_args" with either "1>&3 2>&4" or=
 ">&3 2>&4" (the leading 1 on ">&" in the first option is actually the impl=
ied default, so you can omit it and go for the second option if you like; h=
owever since you can't say "exec 3>&" and have to say "exec 3>&1", I tend t=
o think the first option is more explicitly-clear in what's going on with t=
he file-descriptors).
>=20

Actually=85 you could potentially fix this with one line of code=85

[ "$logging" ] && exec 1>>/tmp/log.stdout 2>>/tmp/log.stderr

And then go remove the "$logging" from the end of each line.
--=20
Devin

_____________
The information contained in this message is proprietary and/or confidentia=
l. If you are not the intended recipient, please: (i) delete the message an=
d all copies; (ii) do not disclose, distribute or use the message in any ma=
nner; and (iii) notify the sender immediately. In addition, please be aware=
 that any message addressed to our domain is subject to archiving and revie=
w by persons other than the intended recipient. Thank you.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?13CA24D6AB415D428143D44749F57D7201F98E98>