[ClusterLabs] ocf scripts shell and local variables
Dejan Muhamedagic
dejanmm at fastmail.fm
Wed Aug 31 10:29:59 UTC 2016
On Tue, Aug 30, 2016 at 06:53:24PM +0200, Lars Ellenberg wrote:
> On Tue, Aug 30, 2016 at 06:15:49PM +0200, Dejan Muhamedagic wrote:
> > On Tue, Aug 30, 2016 at 10:08:00AM -0500, Dmitri Maziuk wrote:
> > > On 2016-08-30 03:44, Dejan Muhamedagic wrote:
> > >
> > > >The kernel reads the shebang line and it is what defines the
> > > >interpreter which is to be invoked to run the script.
> > >
> > > Yes, and does the kernel read when the script is source'd or executed via
> > > any of the mechanisms that have the executable specified in the call,
> > > explicitly or implicitly?
> >
> > I suppose that it is explained in enough detail here:
> >
> > https://en.wikipedia.org/wiki/Shebang_(Unix)
> >
> > In particular:
> >
> > https://en.wikipedia.org/wiki/Shebang_(Unix)#Magic_number
> >
> > > >None of /bin/sh RA requires bash.
> > >
> > > Yeah, only "local".
> >
> > As already mentioned elsewhere in the thread, local is supported
> > in most shell implementations and without it we otherwise
> > wouldn't to be able to maintain software. Not sure where local
> > originates, but wouldn't bet that it's bash.
>
> Let's just agree that as currently implemented,
> our collection of /bin/sh scripts won't run on ksh as shipped with
> solaris (while there likely are ksh derivatives in *BSD somewhere
> that would be mostly fine with them).
I can recall people running some of the BSD systems and they
didn't complain about resource-agents.
> And before this turns even more into a "yes, I'm that old, too" thread,
I guess that is in human nature.
> may I suggest to document that we expect a
> "dash compatible" /bin/sh, and that we expect scripts
> to have a bash shebang (or as appropriate) if they go beyond that.
That is how it has been in resource-agents: POSIX compatible with
the addition of "local". Anyway, every script must have a #! line
which states the right interpreter.
> Then check for incompatible shells in ocf-shellfuncs,
> and just exit early if we detect incompatibilities.
>
> For a suggestion on checking for a proper "local" see below.
> (Add more checks later, if someone feels like it.)
>
> Though, if someone rewrites not the current agents, but the "lib/ocf*"
> help stuff to be sourced by shell based agents in a way that would
> support RAs in all bash, dash, ash, ksh, whatever,
> and the result turns out not too much worse than what we have now,
> I'd have no problem with that...
>
> Cheers,
>
> Lars
>
>
> And for the "typeset" crowd,
> if you think s/local/typeset/ was all that was necessary
> to support function local variables in ksh, think again:
>
> ksh -c '
> function a {
> echo "start of a: x=$x"
> typeset x=a
> echo "before b: x=$x"
> b
> echo "end of a: x=$x"
> }
> function b {
> echo "start of b: x=$x ### HAHA guess this one was unexpected to all but ksh users"
> typeset x=b
> echo "end of b: x=$x"
> }
> x=x
> echo "before a: x=$x"
> a
> echo "after a: x=$x"
> '
>
> Try the same with bash.
:)
> Also remember that sometimes we set a "local" variable in a function
> and expect it to be visible in nested functions, but also set a new
> value in a nested function and expect that value to be reflected
> in the outer scope (up to the last "local").
I hope that this wasn't (ab)used much, it doesn't sound like it
would be easy to follow.
> diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
> index 6d9669d..4151630 100644
> --- a/heartbeat/ocf-shellfuncs.in
> +++ b/heartbeat/ocf-shellfuncs.in
> @@ -920,3 +920,37 @@ ocf_is_true "$OCF_TRACE_RA" && ocf_start_trace
> if ocf_is_true "$HA_use_logd"; then
> : ${HA_LOGD:=yes}
> fi
> +
> +# We use a lot of function local variables with the "local" keyword.
> +# Which works fine with dash and bash,
> +# but does not work with e.g. ksh.
> +# Fail cleanly with a sane error message,
> +# if the current shell does not feel compatible.
> +
> +__ocf_check_for_incompatible_shell_l2()
> +{
> + [ $__ocf_check_for_incompatible_shell_k = v1 ] || return 1
> + local __ocf_check_for_incompatible_shell_k=v2
> + [ $__ocf_check_for_incompatible_shell_k = v2 ] || return 1
> + return 0
> +}
> +
> +__ocf_check_for_incompatible_shell_l1()
> +{
> + [ $__ocf_check_for_incompatible_shell_k = v0 ] || return 1
If there's no "local" and that in the function below fails, won't
this produce a syntax error (due to __ocf_..._k being undefined)?
> + local __ocf_check_for_incompatible_shell_k=v1
> + __ocf_check_for_incompatible_shell_l2
> + [ $__ocf_check_for_incompatible_shell_k = v1 ] || return 1
> + return 0
> +}
> +
> +__ocf_check_for_incompatible_shell()
> +{
> + local __ocf_check_for_incompatible_shell_k=v0
> + __ocf_check_for_incompatible_shell_l1
> + [ $__ocf_check_for_incompatible_shell_k = v0 ] && return 0
> + ocf_exit_reason "Current shell seems to be incompatible. We suggest dash or bash (compatible)."
> + exit $OCF_ERR_GENERIC
> +}
> +
> +__ocf_check_for_incompatible_shell
Looks good otherwise. If somebody's willing to test it on
solaris...
Thanks,
Dejan
>
> _______________________________________________
> Users mailing list: Users at clusterlabs.org
> http://clusterlabs.org/mailman/listinfo/users
>
> Project Home: http://www.clusterlabs.org
> Getting started: http://www.clusterlabs.org/doc/Cluster_from_Scratch.pdf
> Bugs: http://bugs.clusterlabs.org
More information about the Users
mailing list