Git Product home page Git Product logo

bash-concurrent's Introduction

Concurrent version: 2.4.0 language: bash license: MIT Travis

A Bash function to run tasks in parallel and display pretty output as they complete.

asciicast

Examples

Run three tasks concurrently:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1

Run three tasks sequentially:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1  \
    --sequential

Start the medium task after the short task succeeds:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1  \
    --require 'My short task'   \
    --before  'My medium task'

Start the short task after both other tasks succeed:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1  \
    --require 'My long task'    \
    --require 'My medium task'  \
    --before  'My short task'

Same as above, but shorter:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1  \
    --require-all --before 'My short task'

Start the medium task and the long task after the short task succeeds:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1  \
    --require 'My short task'   \
    --before  'My medium task'  \
    --before  'My long task'

Same as above, but shorter:

concurrent \
    - 'My long task'   sleep 10 \
    - 'My medium task' sleep 5  \
    - 'My short task'  sleep 1  \
    --require 'My short task' --before-all

Run the first two tasks concurrently, and then the second two tasks concurrently, and then the final three tasks concurrently.

concurrent \
    - 'Task 1'  sleep 3 \
    - 'Task 2'  sleep 3 \
    --and-then \
    - 'Task 3'  sleep 3 \
    - 'Task 4'  sleep 3 \
    --and-then \
    - 'Task 5'  sleep 3 \
    - 'Task 6'  sleep 3 \
    - 'Task 7'  sleep 3

If your command has a - argument, you can use a different task delimiter:

concurrent \
    + 'My long task'   wget -O - ... \
    + 'My medium task' sleep 5  \
    + 'My short task'  sleep 1

You can display extra information at the end of each task's status line by echoing to fd 3.

my_task() {
    ...
    echo "(extra info)" >&3
    ...
}

Take a look at demo.sh for more involved examples.

Dry Run

If you have a lot of dependencies between tasks, it's generally a good idea to perform a dry-run to ensure that the tasks are ordered as expected. Set the CONCURRENT_DRY_RUN environment variable to perform a dry-run.

Forking Limit

By default, concurrent allows up to 50 concurrently-running tasks. Set the CONCURRENT_LIMIT environment variable to override this limit.

A neat trick is to set the limit to 1, essentially forcing a --sequential run, but with existing tasks between dependencies taken into account.

A limit less than 1 is treated as no limit.

Compact Display

If the number of tasks exceed the terminal height, the "compact display" will be activated. It can also be explicitly activated by setting the CONCURRENT_COMPACT environment variable to anything other than 0.

In this mode, each task is represented by a single character instead of an entire line. An execution summary is displayed above the tasks.

asciicast

Non-Interactive Mode

If the output is not attached to a tty, the "non-interactive" mode will be activated. It can also be explicitly activated by setting the CONCURRENT_NONINTERACTIVE environment variable to anything other than 0.

In this mode, each task is displayed as soon as it completes. Colors are also disabled.

Logging

By default, logs for each task will be created in ./logs/<timestamp>/. For example:

$ ls .logs/2016-02-02@00:09:07
0. Creating VM (0).log
1. Creating ramdisk (0).log
2. Enabling swap (0).log
3. Populating VM with world data (1).log
4. Spigot: Pulling docker image for build (1).log
5. Spigot: Building JAR (skip).log
6. Pulling remaining docker images (skip).log
7. Launching services (skip).log

To change this directory, set CONCURRENT_LOG_DIR before calling concurrent.

Failure Demo

asciicast

Interrupted Demo

asciicast

Requirements

  • bash >= 4.2 (for declare -g)
  • cat
  • cp
  • date
  • mkdir
  • mkfifo
  • mktemp
  • mv
  • sed
  • tail
  • tput

Change Log

  • 2.4.0
    • New: Gracefully switches to non-interactive mode when a tty is not present or if CONCURRENT_NONINTERACTIVE is non-zero.
  • 2.3.3
    • Fix: Cursor no longer hidden when running nested.
  • 2.3.2
    • Fix: Failing tasks with no output now exit with the correct status (credit: @uluyol).
  • 2.3.1
    • Fix: Now clearing to end of line when printing extra status info after a task (credit: @fragmede).
  • 2.3.0
    • New: Concurrency limit defaults to 50, unless overridden by CONCURRENT_LIMIT.
    • New: If the number of tasks exceed the terminal height (or CONCURRENT_COMPACT is set), each task will be displayed as a single character instead of a taking up an entire line.
    • New: Cursor now hidden while running.
    • Fix: Greatly improved speed of event loop. Especially noticeable for large numbers of tasks.
    • Fix: Namespaced command_* and prereq_* arrays so that they don't carry into the tasks.
  • 2.2.1
    • Fix: Tasks not allowed to read from stdin.
  • 2.2.0
    • New: Instances of concurrent can be nested without breaking.
    • New: Set custom log dir with CONCURRENT_LOG_DIR.
    • Fix: Works under Cygwin (special thanks to @FredDeschenes).
    • Fix: No longer requires GNU sed (gsed) on OS X.
    • Fix: Animation now uses a single process.
    • Fix: Extra status info is now merely bold instead of bold/white, which should be more visible on light terminal backgrounds.
  • 2.1.0
    • New: New --and-then flag for dividing tasks into groups. All tasks in a group run concurrently, but all must complete before the next group may start (inspiration: fooshards on Reddit).
    • Fix: Removed extra backslashes in README (credit: bloody-albatross on Reddit)
  • 2.0.1
    • Fix: kill is a bash builtin (credit: @ScoreUnder)
    • Fix: Require GNU sed on OS X (credit: @kumon)
    • Fix: Static analysis with shellcheck on push via Travis CI (credit: @xzovy)
    • Fix: Cleaner signal handling.
    • Fix: Simplified event loop.
  • 2.0.0
    • New: Tasks can now display status updates by echoing to fd 3.
  • 1.6.0
    • New: CONCURRENT_DRY_RUN environment variable runs sleep 3 instead of actual commands (and prints message).
  • 1.5.2
    • Fix: Requirement loops disallowed.
  • 1.5.1
    • Fix: Task is not allowed to require itself directly.
  • 1.5.0
    • New: First argument is now the task delimiter.
  • 1.4.1
    • Fix: Namespaced previously-missed function.
  • 1.4.0
    • New: New --require-all and --before-all flags.
    • Fix: Namespaced all concurrent-related functions and variables.
    • Fix: Unsetting all concurrent-related functions and variables in the task's context.
    • Fix: Enforcing foreground in an interactive shell.
  • 1.3.0
    • New: New --sequential flag, for when each task requires the previous.
  • 1.2.0
    • New: Running tasks have an animated cursor.
    • Fix: Enforcing bash version 4.3.
    • Fix: Echo is re-enabled even if an internal error occurs.
  • 1.1.6
    • Fix: Enforcing bash version 4.
  • 1.1.5
    • Fix: Tasks now use original $PWD and $OLDPWD.
  • 1.1.4
    • Fix: Tasks now use original $SHELLOPTS and $BASHOPTS.
  • 1.1.3
    • Fix: Sanitizing forward slashes from log names.
  • 1.1.2
    • Fix: Ensuring task status file exists even if an internal error occurs.
  • 1.1.1
    • Fix: Task command may now have arguments starting with -.
  • 1.1.0
    • New: Gracefully handling SIGINT.
    • Fix: Works on OS X too.
  • 1.0.0
    • Initial working release.

bash-concurrent's People

Contributors

fragmede avatar kumon avatar partyimp avatar scoreunder avatar themattrix avatar uluyol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bash-concurrent's Issues

Gracefully handle running without a tty.

Interactive output can be disabled by manually setting CONCURRENT_DEPTH to 0 or higher. Unfortunately this still requires the TERM environment variable to be valid so that the call to tput succeeds (when checking the number of terminal columns).

It's also non-intuitive and undocumented.

A better solution would be to automatically determine if the output is not connected to a tty and gracefully disable interactive output.

Acceptance Criteria:

  • When run without a tty, interactive output is disabled.
  • When run without a tty, colors are disabled.
  • When run without a tty, TERM can be unset.
  • When run without a tty, each task line is displayed as soon as it completes.

Request to define all variables before use and check for undefined variables

This is more of a feature request than an issue. This library is fantastic and I've used it for many years.

I like to run scripts with the so called bash strict mode:
set -euo pipefail

This helps to avoid unexpended errors due to undefined variables etc.

When I try and run a script leveraging bash concurrency I cannot set -u because of undefined variables.

Would it be possible to define defaults for CONCURRENT_DRY_RUN and to check if remaining_args is undefined.

Immediate Failure event-pipe error

I haven't been able to narrow when or how I get this error:

screen shot 2018-09-28 at 12 15 48 am

But it usually occurs when I run quite a large script over and over again. Restarting the computer usually fixes this, but not always.

Once my system gets in this "state", I can't even run the demo.sh file in this repo.

On this system, the current $TMPDIR is /var/folders/6b/mm5f4rz116lbp_9rphrmv4s00000gn/T/

This line of code:

__crt__status_dir=$(mktemp -d "${TMPDIR:-/tmp}/concurrent.lib.sh.XXXXXXXXXXX")

__crt__status_dir=$(mktemp -d "${TMPDIR:-/tmp}/concurrent.lib.sh.XXXXXXXXXXX")

ultimately generates a .../T//concurrent... which is odd, but I don't think is the problem.

Interestingly, I can login to a different user account, and the demo file works, log back in to the original and still have the problem.

An "--and-then" flag should separate groups of concurrent tasks.

For example,

concurrent \
    - 'Task 1'   cmd_1 \
    - 'Task 2'   cmd_2 \
    --and-then \
    - 'Task 3'   cmd_3 \
    - 'Task 4'   cmd_4 \
    --and-then \
    - 'Task 5'   cmd_5

This would be shorthand for:

concurrent \
    - 'Task 1'   cmd_1 \
    - 'Task 2'   cmd_2 \
    - 'Task 3'   cmd_3 \
    - 'Task 4'   cmd_4 \
    - 'Task 5'   cmd_5 \
    \
    --require 'Task 1' \
    --before  'Task 3' \
    --before  'Task 4' \
    \
    --require 'Task 2' \
    --before  'Task 3' \
    --before  'Task 4' \
    \
    --require 'Task 3' \
    --before  'Task 5' \
    \
    --require 'Task 4' \
    --before  'Task 5'

bash 5.x support

the compatibility check fails for bash 5.x due to minor version check

bash-5.0# bash -x foo.sh 
+ source concurrent.lib.sh
+ concurrent - 'sleep test' sleep 1
+ [[ -z 5 0 0 1 release x86_64-pc-linux-musl ]]
+ [[ 5 -lt 4 ]]
+ [[ 0 -lt 2 ]]
+ __crt__error 'Requires Bash version 4.2 for '\''declare -g'\'' (you have 5.0.0(1)-release)'
+ echo 'ERROR (concurrent): Requires Bash version 4.2 for '\''declare -g'\'' (you have 5.0.0(1)-release)'
ERROR (concurrent): Requires Bash version 4.2 for 'declare -g' (you have 5.0.0(1)-release)
+ exit 1

Does this work with zsh?

I checked the code superficially, it seems the only place it uses sth BASH specific is BASHOPTS?

Demo hangs on Cygwin

Demo just seems to "hang" on the first step, even though the 'my_sleep' function executes and returns properly. It also does it in dry run mode (as shown in the screenshot), which suggests this most likely isn't an issue with the demo.

Stuck

At first glance nothing unsupported by a basic Cygwin install seems to be used, which makes this even more puzzling.

I'll take a look tomorrow evening, but if anyone has any ideas in the meantime, feel free to share!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.