[colug-432] First script - would anyone care to review?
Zach Villers
zachvatwork at gmail.com
Fri Jun 5 00:01:43 EDT 2015
Thank you both so much!
I can tell you really spent some time going through everything. I'm going to implement many of your suggestions.
Today I added this script into a kickstart file and used a here doc to create the two .ldif files. I will work back through my use of single and double quotes and back ticks as well as define some variables up front.
Thanks again for the review!
> On Jun 4, 2015, at 11:09 PM, Rick Hornsby <richardjhornsby at gmail.com> wrote:
>
>
>
> Stephen Potter wrote:
>> Zach-
>> Overall, this looks like fairly clean code.
> Most of my comments are around improvements, rather than any fatal
> issues. I explain _why_ I point out certain improvements, and I want to
> be clear - those reasons should not be taken as a reflection on or a
> personal criticism of you.
>
> For a first script, I'm impressed for the same reason - you've obviously
> taken care and pain to write readable code and provide plenty of
> comments. Keep doing that. I don't see anything that's too insane or
> crazy or that I'd give you a bad grade over. It is nicely formatted,
> most of your indenting is where it should be and not all crazy jacked up.
>
> Most of your certutil and pk12util commands are called out with a short
> description. Keep doing this. You will be glad you did, and so will
> those who read your code long after you abandon it.
>
> +1 for avoiding the useless use of cat.
>> I do, however, see a lot of
>> code duplication that could lead to typos or forgetting to update a
>> particular section during script maintenance. For example, not that
>> this currently affects the script, look at the difference between lines
>> 25, 39, and 46. You have used double quotes in one case and single
>> quotes in the others.
> Be careful with your quoting, especially in shell scripts. double quote
> and single quote can have very different, and mutually exclusive,
> consequences.
>
> There is an alternative syntax to the backticks that I encourage my
> engineers to use because I find it is much easier to read. These two
> are functionally equivalent:
>
> $ipaddr=`ip addr`
>
> $ipaddr=$(ip addr)
>
> The backticks can be hard to tell apart from the single quote
> character. In the end, this is a personal choice. I see both in your
> script. Try not to mix and match the styles.
>
>
> nit: $ipadrss -> prefer the more common usage $ipaddr
>
>
>> From an efficiency standpoint, I also see several places where you run
>> the same command multiple times to get different information each time,
>> where you might be able to tighten it up and only do it once. However,
>> in this day and age with the speed of systems, this kind of efficiency
>> may no longer be something to be concerned about.
> If it isn't necessary to ask the system to do the same thing multiple
> times, it's just generally better not to. Duplicating a command does go
> to maintainability and readability. Use variables instead of repeating
> the same string/path/command over and over. This is more true for
> custom paths than standard or reasonably well-known ones, but could be
> applied to both.
>
> "Use variables" applies not just to the result of commands, but to
> things that you're using multiple times as well, like the path
>
> /root/ldapca
>
> I see this path repeated many times. Set it once somewhere near the top
> and use the variable for the remainder. You will be much happier when
> you need to change that path or reference it again. By using the
> variable, you help ensure that you don't accidentally forget an 's' in
> cacpassword in one place, or change the path half-way through and not
> realize it. For example:
>
> ldapca_path=/root/ldapca
> capassword_file=$ldapca_path/capassword
>
> (I use _path and _file here because I'm trying to reduce ambiguity of
> the variable name. Is 'capassword' a string representing a password?
> No, in this case it represents a file so I call it out in the variable
> name.)
>
> Using the variable also helps make clear to your reader what you intend,
> and makes it easier to spot something you didn't intend or mean to do.
>
> cd /root/ldapca
>
> This might just be my personal preference, but if I were providing a
> critique to one of my students or engineers, I would say don't do cd in
> your scripts unless it is absolutely and completely necessary, which it
> almost never is. You're globally altering the context of your script's
> execution and then depending on a relative path to be correct. An
> altered context like this is very, very hard to keep track of and makes
> it much harder to read into what the full path is later in a script,
> separated from this cd command.
>
>
> [ $? -eq 0 ] && echo "localhost ok" || { echo "localhost not ok";
> exit 1; } ;;
>
> Be very sparing about using complex expressions like this. Within
> reason, if there is a more readable way to write something, choose
> readable over terse. That's a general critique both for your future
> self and future maintainers. Try not to bury critical code branch
> changes (ie terminal fault handling) inside a single line like that. It
> makes it easy to miss the 'exit 1' when reading and troubleshooting ---
> and makes it much harder to modify the behavior later if needed.
>
> I know it looks cooler and more geek-cred to write complex single line
> chains, but it is much less readable and far less maintainable over time.
>
> I worked with a coder some years back who wrote terse, complex messes
> because he thought it made him look smarter and gave him the false sense
> that he alone owned his code. No one else could understand it enough to
> monkey with it. Needless to say, he was lousy at his job because in the
> real world people have to collaborate. I wasn't out to change his code
> - but I was trying to use it. Without much documentation or commenting,
> I was forced to try to wade through the swamp of frustration - wasting
> tons of time. When something he wrote wasn't working properly, it would
> take much longer to get it fixed.
>
> [ -f /etc/openldap/changes.ldif ] && { ldapmodify -Y EXTERNAL -H
> ldapi:/// -f /etc/openldap/changes.ldif; } || { echo "failed to modify
> changes.ldif"; exit 1; }
>
> That line is too long and as mentioned above, too complex for a single
> line. It is too complex because you're squashing tests and
> object/state/system modifying actions and a terminating fault command
> into a single line - basically one long statement. Break it down -
> while it takes more lines, it is much more readable and easier to maintain.
>
> [ -f /usr/share/migrationtools/migrate_common.ph ] && { sed -i
> 's/"padl.com"/"example.com"/'
> /usr/share/migrationtools/migrate_common.ph; } && { sed -i
> 's/"dc=padl,dc=com"/"dc=example,dc=com"/'
> /usr/share/migrationtools/migrate_common.ph; }
>
> At the risk of sounding like I'm harping on the same theme, please don't
> do this.
>
> Here's a rule of thumb - if a line seems like a run-on sentence, it
> probably is.
>
> Sometimes long lines (some of your certutil commands) are reasonably
> unavoidable.
>> From an output perspective, if you have more than one of a particular
>> network interface (eth0, eth1, for example), your output doesn't readily
>> identify which one works or doesn't work, which makes troubleshooting a
>> bit more difficult. Again, with the types of systems you are probably
>> running this on, it probably doesn't significantly affect you, but it is
>> something to think about as you develop more complex scripts with
>> additional inputs and outputs. You might want to include $netw in your
>> output to identify the interfaces.
> Agreed. Try also in general to do a little bit more error checking,
> with reasonable explanations and if possible a resolution or two for a
> failure.
>
> You do some sanity checking, but you also run very long series of
> commands without making sure any of them worked before moving on. As
> Stephen points out, it may not matter too much here but it is something
> to think about.
>
> Along these same lines, be careful with the append redirect. It takes
> more work, but it is useful to check before using an append to make a
> configuration change. Say the script got half-way through and broke.
> Fix, run it again - the appends that happened before the script broke
> are going to happen again - duplicating configuration inside your config
> files which is messy and may have unintended consequences.
>
> Using >> when you're writing to a log file - who cares. Modifying
> pre-existing configuration files is a little different case.
>>
>> I do see one particular error in the host networking case script. Line
>> 26 is attempting to cut information from a string, but the cut command
>> takes a file as input. To get this to work (you don't actually use it,
>> because you have the lines that use it commented out), you would need to
>> do an "echo $netw | cut".
>
> At the end of each case statement, put the closing ;; on its own line
> for readability.
>
>>
>> An interesting thing you might want to look into to bring your scripting
>> to the next level. You have a couple of places where you do several
>> echo statements that append to a file (lines 124-131 and 148-150, for
>> example). You could make these a little easier to read (and save
>> yourself some keystrokes, which are always prone to typos) if you use
>> "cat" and a "heredoc", like:
>>
>> cat<<EndofLdapConf>> /etc/openldap/ldap.conf
>> URI ldap://instructor.example.com
>> BASE dc=example,dc=true
>> TLS_REQUIRE allow
>> EndofLdapConf
> +1 to the HEREDOC suggestion. The way you did it is fine - there's
> nothing wrong with how it is. Stephen is correct though, for a long
> block like this it might be a little better as a HEREDOC statement.
>
>
> #enable logging
>
> echo "local4.* /var/log/ldap.log" >> /etc/rsyslog.conf
> systemctl restart rsyslog
>
> Move this to be way earlier in your script. Nothing about what you're
> doing depends on it being at the end, but it could help a great deal in
> troubleshooting to have the logs available before starting slapd, ssd, etc.
>
>
> One last thing - the last thing, actually - try to explicitly exit with
> 0. It is not required, it will happen automagically etc etc - having it
> as the last thing you do will make your script a bit more readable and
> assure your reader that a) you intend to end things at this point and b)
> they can reasonably expect the return value / exit code to be 0 unless
> something has gone wrong.
>
> Overall, this looks pretty good. Keep at it.
>
> exit 0
>
> _______________________________________________
> colug-432 mailing list
> colug-432 at colug.net
> http://lists.colug.net/mailman/listinfo/colug-432
More information about the colug-432
mailing list