Score:0

How to convert BASH script to DASH or other solutions?

ng flag

I am creating an AWS distributor package to modify the syslog configuration on different flavors of Linux servers. I wrote a few simple bash scripts to handle the install, uninstall, and update. I thought this would be universal. However, today I found out that AWS uses sh to execute the script (i.e. sh install.sh) and on Ubuntu/Debian this defaults to DASH and not BASH. For that reason my scripts fail with:

update errors: update.sh: 3: update.sh: function: not found

update.sh: 9: update.sh: Syntax error: "}" unexpected

failed to run commands: exit status 2

Failed to install package; install status Failed

I can't change the AWS behavior. And I don't want to modify any configurations on the server. So, it would appear my only options are that which modify the script file itself?

The first preference would be to make the script universal so it can run on any flavor of Linux. The second preference would be to create a different script for Debian that is DASH compatible.

Unfortunately, I don't find much information about dash programming. Any suggestions?

The 3 scripts in question are....

install.sh

#!/bin/bash

function isInstalled {
  if sudo ls /etc/rsyslog.d/xdr.conf >/dev/null 2>&1; then
    true
  else
    false
  fi
}

if isInstalled; then
  exit 0
else
  sudo cp xdr.conf /etc/rsyslog.d/xdr.conf
  sudo service rsyslog restart
fi

uninstall.sh

#!/bin/bash

function isInstalled {
  if sudo ls /etc/rsyslog.d/xdr.conf >/dev/null 2>&1; then
    true
  else
    false
  fi
}

if isInstalled; then
  sudo rm /etc/rsyslog.d/xdr.conf
  sudo service rsyslog restart
else
  exit 0
fi

update.sh

#!/bin/bash

function isDiff {
  if sudo diff xdr.conf /etc/rsyslog.d/xdr.conf >/dev/null 2>&1; then
    false
  else
    true
  fi
}

if isDiff; then
  sudo cp xdr.conf /etc/rsyslog.d/xdr.conf
  sudo service rsyslog restart
else
  exit 0
fi
ph flag
If you change the shebang to `#!/bin/sh`, [shellcheck.net](https://www.shellcheck.net) will point out that you're using a nonstandard syntax to define your functions. Also, see ["Dash as /bin/sh"](https://wiki.ubuntu.com/DashAsBinSh) in the Ununtu wiki, and the `checkbashisms` tool it describes.
Score:1
us flag

There are two different function syntaxes in bash/ksh/zsh. You're using the ksh style: function name { … }. The other form is just name() { … } and is the form introduced late in the original Bourne shell.

It really is pointless to do:

    if cmd; then
      true
    else
      false
    fi

Apart from turning all non-zero return statuses to 1, this is just the same as just running cmd. And with the function reduced to just one line, you really don't need a function. I'd also be tempted to use cmp -s instead of diff or to simply do the copy unconditionally. And don't use ls to test for the existence of a file. Either the test command or the [ is intended for that purpose: [ -e /etc/rsyslog.d/xdr.conf ]. That does exist in external form if you have sudo.

Appleoddity avatar
ng flag
Hi. I will take your suggestions in to consideration for comparing/testing files. But, the purpose of the test is because I do not want the syslog daemon always being restarted. This script is something that will run on a daily basis as part of making sure the instance is configured and/or updated if the configuration changes. It should exit with a 0 code so that AWS thinks it is OK. Or a non-zero code to indicate a problem.
ph flag
@Appleoddity The point is that e.g. the `isInstalled` function could just be defined as `isInstalled() { [ -e /etc/rsyslog.d/xdr.conf ]; }` -- it'll return the status of the test directly, with no `if`, `true`, `false`, etc needed. Or, you could skip the function entirely, and in the main part of the script, use `if [ -e /etc/rsyslog.d/xdr.conf ]; then ...`.
Appleoddity avatar
ng flag
@GordonDavisson ok. Thank you. I’ll have to do some research to better understand this syntax. Are you suggesting that this syntax would be compatible with bash and dash?
ph flag
@Appleoddity Yes, that syntax should work in any POSIX-compliant shell (bash, dash, ksh, etc), and I think even pre-POSIX Bourne-style shells (but not with non-Bourne-style shells like csh or fish).
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.