0

I have general question about chaining commands to one specific binary in bash shell, with examples from Magento (use case)

In Magento you commonly want to chain many commands together - they take ages so in order to run as batch you might do: bin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush

Initially I was adding these command chains to ~/.bash_aliases, but it wasn't as easy as I thought to get consistent groups of commands.

I already add the binary to my PATH, but I want to know whether you can chain commands so that it then looks like this: mag_chain setup:upgrade setup:di:compile cache:flush

Is this possible?

If not is there a solution with bash that puts me in the right direction?

1 Answer 1

1

bash doesn't have a built-in way to do this, but you can script it without too much trouble. The main tricky thing is to be able to figure out where one command ends and the next begins. I don't know magneto, so this is an implausible example, but suppose you were to run

mag_chain help setup:upgrade

...should it do magento help && magento setup:upgrade, or just magento help setup:upgrade? One possibility is to use quotes to pass each separate command as a single argument:

mag_chain help setup:upgrade     # -> magento help && magento setup:upgrade
mag_chain "help setup:upgrade"   # -> magento help setup:upgrade

There is a bit of mess with splitting a single command's arguments. bash has a built-in way to do this, by using the parameter without double-quotes, but that has weird problems in some cases; xargs does a much more reasonable job of splitting words, so use that.

Some other things to worry about: make sure to check each step for an error, and cancel the rest of the chain if there is one. Also, I'm not sure what the actual magneto command itself should be. You used bin/magneto, but that assumes the magneto file is directly executable (i.e. you don't need php bin/magneto), and that it's in a "bin" directory directly under the current working directory. So I put the magneto command in an array so it's easy to change.

#!/bin/bash

magneto_command=(bin/magneto)

if [[ $# -eq 0 ]]; then
    echo "Usage: $0 magneto_command [magneto_command...]" >&2
    exit 1
fi

for subcommand in "$@"; do
    xargs -o "${magneto_command[@]}" <<<"$subcommand" || {
        status=$?
        echo "Remainder of chain cancelled" >&2
        exit $status
    }
done
4
  • Thanks, looks interesting & will try soon. Don't need php suffixes fortunately, and also there is no help prefix like that, as far as I am aware it is always [binary] [functional command] Jan 2, 2021 at 10:29
  • It works well, one question - what does wrapping bin/magento in brackets do? I wanted to check that the binary is executable before running the rest of the script (if [ ! -x $magento_binary ]; then ... but the brackets interfere. Can I do xargs -o "${(magento_binary)[@]}" or something in-script instead? Jan 3, 2021 at 11:05
  • @ScottAnderson What's magento_binary? Is that what I called magneto_command (in which case I think it's better name for the variable)? If so, you really want to just test the first element of it, and put double-quotes around it, and in bash I'd also prefer [[ ]] to [ ]. Like this: if [[ -e "${magento_binary[0]}" ]]. This should work if it's just bin/magneto, but if you do need to use php bin/magneto (i.e. magento_binary=(php bin/magneto), then it'll fail because pip isn't an executable in the current directory. Jan 3, 2021 at 22:37
  • Yeah magento_binary the variable for bin/magento. Thanks for the further solution :) Jan 4, 2021 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.