0

A while ago, we upgraded to the latest version of Laravel Mix. This has a much more visual output when running commands like yarn mix --production, but it creates an issue for us on tools like Forge and Ploi, since the progress bar is not seen by these tools, and our deployment return an error, since Forge and Ploi think that the command is stuck, as it runs for 5 - 15 minutes due to the huge amount of code it needs to compile.

While we are working on optimizing our code to reduce compilation time, I am looking for a way to get the current code compiled in Forge or Ploi. I came up with the following idea:

If the progress bar is not seen, maybe I can echo a line of text as long as the command runs, which hopefully will prevent the timeout. To achieve this, I created the following script:

COUNTER=0;
while yarn mix --production &> /dev/null;
do
  echo "Running for" $COUNTER "seconds";
  sleep 10;
  let "COUNTER += 10";
done

... but this doesn't seem to do the trick as nothing is printed after 10 seconds. I'm a noob with bash, so maybe someone can help me point out what I'm doing wrong?

PS: I'm doing &> /dev/null to avoid having both the counter and the progress bar, as the --no-progress flag doesn't seem to do that.

Gerard
  • 38
  • 5
  • `&> /dev/null` will discard any output... – Jetchisel Sep 23 '22 at 09:41
  • even if I remove the `&> /dev/null`, I see the progress-bar, but not the echo-ed counter. – Gerard Sep 23 '22 at 09:44
  • All those /dev/null things are just about display. It is irrelevant to the while condition, which depends on exit code. And < /dev/null is redirecting input. – chrslg Sep 23 '22 at 09:58

2 Answers2

3

Well, you need to run your command in the background if you want to be able to do something else while it runs. Otherwise, while condition will be evaluated only when yarn is finished

You need something like :

yarn mix --production < /dev/null 1> /dev/null &
pid=$!
COUNTER=0;
while kill -0 $pid &> /dev/null
do
  echo "Running for" $COUNTER "seconds";
  sleep 10;
  let "COUNTER += 10";
done

Edit: replaced jobs -p | grep -q $pid by kill -0 $pid &> /dev/null after Jetchisel's comment. It's better than piping the output of jobs and feeding it to a grep subprocess...

chrslg
  • 9,023
  • 5
  • 17
  • 31
  • 1
    `while kill -0 "$pid"...` – Jetchisel Sep 23 '22 at 10:00
  • 1
    Better indeed. I didn't know this kill -0 thing. It is not even documented in my man page (except that it says that, among possible signals, is -0. But with no indication about what for. But indeed, other man pages on the web clarify it: it does nothing but still check error) – chrslg Sep 23 '22 at 10:20
  • A ``&> /dev/null`` is needed, unless you know a secret -quiet flag to kill? :D – chrslg Sep 23 '22 at 10:22
  • 1
    I edit my answer to integrate your "kill" – chrslg Sep 23 '22 at 10:23
  • I don't think there is flag for a quite kill. :-) – Jetchisel Sep 23 '22 at 10:23
  • `kill` is also a builtin from the shell. It has an external executable as well. – Jetchisel Sep 23 '22 at 10:26
  • 1
    Yep. That's why it is better than jobs | grep. jobs is also a builtin. But grep isn't. So, jobs|grep forks a subprocess, when your kill -0 doesn't. It is always better to avoid subprocess, especially for "atomic" tasks: the time needed just to fork/exec is bigger than the time used to perform the actual task. – chrslg Sep 23 '22 at 10:28
  • 1
    Since I don't have access to yarn, I guess we both learned something from this, upvoted. – Jetchisel Sep 23 '22 at 10:30
  • I could also have used a pure bash grep tho. Like ``x=$(jobs -p)`` and then ``[[ -z "${x#$pid}" ]]``. No subprocess. But still, heavier to write. And probably slower also. – chrslg Sep 23 '22 at 10:31
  • Thanks for the answers! I needed to change the first line to `yarn mix --production < /dev/null 1> /dev/null &` to make sure the command doesn't get suspended after it finished running, while still showing errors. Can you update that in your answer, @chrslg ? Then I can mark your answer as accepted :-) – Gerard Sep 23 '22 at 12:23
  • Yep, the < /dev/null cannot hurt, indeed. – chrslg Sep 23 '22 at 13:14
0

Here is how I did waiting animation in my sshto and kube-dialog projects:

Waiting(animation) function:

   x=$[COLUMNS/2-3]
   y=$[  LINES/2-3]
sand=( ⠁  ⠂  ⠄  ' ' )
#  {   small digits    }
sd=(₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉)
bs='⠴⠷⠦' # bottom sand pile
ts='⠖'    #  top  sand pile
WAIT(){
    clear; cursor off; i=0; start=$SECONDS
    XY $[x-1]  $y    $UND$BLD$RED'       '$DEF                     # _______
    XY $[x-1] $[y+1]         $RED'╲'$DIM$UND'     '$DEF$red'╱'$DEF # ╲_____╱
    XY  $x    $[y+2]         $BLU'(  '$BLD$WHT'•'$BLD$BLU')'$DEF   #  (  •)
    XY  $x    $[y+3]         $BLU' ╲'$YLW"$ts"$BLD$BLU'╱'$DEF      #   ╲⠖╱
    XY  $x    $[y+4]         $BLU" ╱$YLW${sand[$i]}$BLD$BLU╲"$DEF  #   ╱⠂╲
    XY  $x    $[y+5]         $BLU'('$YLW"$bs"$BLD$BLU')'$DEF       #  (⠴⠷⠦)
    XY $[x-1] $[y+6]         $RED'╱'$RED'‾‾‾‾‾'$BLD$RED'╲'$DEF     # ╱‾‾‾‾‾╲
    XY $[x-1] $[y+7]     $DIM$RED'‾‾‾‾‾‾‾'$DEF                     # ‾‾‾‾‾‾‾
    ( while true; do sleep 0.07
        printf -v counter "%03d" $[SECONDS-start]
        small="${sd[${counter:0:1}]}${sd[${counter:1:1}]}${sd[${counter:2:1}]}"
        XY $[x-1] $[y+1] $RED'╲'$DIM$UND" $small "$DEF$red'╱'$DEF
        XY  $x    $[y+4] $BLU" ╱$YLW${sand[$i]}$BLD$BLU╲"$DEF
        ((i++)); (($i==${#sand[@]})) && i=0;
    done ) & waiter=$!
}

Color vars, 'XY' and 'cursor' functions are from here.

Stop animation function:

GO() { [[ -e /proc/$waiter ]] && kill $waiter; cursor on; clear; }

And here is how to start some command using it:

WAIT; some_command &> /dev/null; GO

The trick is not the main command gone to background but 'waiter'. This way you can wait for not only one command but many:

WAIT
cmd1 &> /dev/null
cmd2 &> /dev/null
cmd3 &> /dev/null
GO

The animation:

waiting animation

p.s. another example with cp animation here.

Ivan
  • 6,188
  • 1
  • 16
  • 23