File: parallel.sh

package info (click to toggle)
cfengine3 3.24.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 37,552 kB
  • sloc: ansic: 163,161; sh: 10,296; python: 2,950; makefile: 1,744; lex: 784; yacc: 633; perl: 211; pascal: 157; xml: 21; sed: 13
file content (138 lines) | stat: -rw-r--r-- 2,975 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# A shell "library" providing a function to run a given command on multiple
# arguments in parallel.
#
# For best results, make sure 'parallel' is installed.
#

if type parallel >/dev/null 2>&1; then
  HAVE_PARALLEL=1
else
  HAVE_PARALLEL=0
fi

if type xargs >/dev/null 2>&1; then
  HAVE_XARGS=1
else
  HAVE_XARGS=0
fi

if type getconf >/dev/null 2>&1; then
  NCPUs="$(getconf _NPROCESSORS_ONLN)"
else
  NCPUs="$(grep processor /proc/cpuinfo | wc -l)"
fi


_run_using_parallel() {
  max_jobs=""
  if [ $# -gt 2 ]; then
    max_jobs="-j$3"
  fi

  if [ "$2" = "-" ]; then
    parallel $max_jobs "$1 {}"
  else
    parallel $max_jobs "$1 {}" :::: "$2"
  fi
  return $?
}

_run_using_xargs() {
  if [ $# -gt 2 ]; then
    max_jobs="-P$3"
  else
    max_jobs="-P$NCPUs"
  fi

  if [ "$2" = "-" ]; then
    xargs -n1 $max_jobs "$1"
  else
    xargs -n1 $max_jobs -a "$2" "$1"
  fi
  return $?
}

_run_using_for() {
  if [ $# -gt 2 ]; then
    job_slots="$3"
  else
    job_slots="$NCPUs"
  fi

  if [ "$2" = "-" ]; then
    input_arg="/dev/stdin"
  else
    input_arg="$2"
  fi
  failure=0
  while read item; do
    if [ "$job_slots" = 0 ]; then
      wait -n
      if [ $? != 0 ] && [ $failure = 0 ]; then
        failure=1
      fi
      job_slots="$(expr $job_slots + 1)"
    fi
    "$1" "$item" &
    job_slots="$(expr $job_slots - 1)"
  done < $input_arg

  # wait for the jobs one by one and check the exit statuses (127 means there
  # are no more jobs to wait for)
  wait -n
  exit_status=$?
  while [ $exit_status != 127 ]; do
    wait -n
    exit_status=$?
    if [ $exit_status != 0 ] && [ $exit_status != 127 ] && [ $failure = 0 ]; then
      failure=1
    fi
  done
  return $failure
}

run_in_parallel() {
  # Run the given command with the read arguments in parallel
  #
  # $1     -- command to run
  # $2     -- path to the file to read the argument items from,
  #           or "-" to load from STDIN
  # $3     -- OPTIONAL, maximum number of parallel jobs to run,
  #           defaults to the number of CPUs
  # return -- 0 if all runs of the command exited with 0, 1 otherwise
  #
  # Reads the arguments (one arg per line) and runs the given command in
  # parallel with them. One argument per command. Uses 'parallel', 'xargs' or a
  # for-loop with background jobs in respective order of preference.

  # we need to know if $1 is a function because 'xargs' doesn't support
  # functions at all and for 'parallel' we need to export the function
  if type "$1" | head -n1 | grep "$1 is a function" >/dev/null; then
    IS_A_FUNC=1
  else
    IS_A_FUNC=0
  fi

  if [ $HAVE_PARALLEL = 1 ]; then
    if [ $IS_A_FUNC = 1 ]; then
      export -f "$1"
    fi

    _run_using_parallel "$@"
    if [ $? = 0 ]; then
      return 0
    else
      return 1
    fi
  elif [ $HAVE_XARGS = 1 ] && [ $IS_A_FUNC != 1 ]; then
    _run_using_xargs "$@"
    if [ $? = 0 ]; then
      return 0
    else
      return 1
    fi
  else
    _run_using_for "$@"
    return $?
  fi
}