| #!/bin/bash |
| # |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| # Author: sligocki@google.com (Shawn Ligocki) |
| # |
| # Helper functions for holding locks so that checkin tests from two clients |
| # can be run simultaneously, and printing status on long-running commands. |
| # |
| # Sourced from checkin.make. |
| |
| readonly APACHE_LOCKFILE="/tmp/pagespeed-apache.lock" |
| |
| function acquire_lock { |
| local server=$1 |
| local lockfile=$2 |
| |
| local lockfile_tmp="$lockfile.$$" |
| local printed_msg=0 |
| |
| echo $$ > "$lockfile_tmp" |
| # ln will fail if $lockfile exists, making this an atomic test and set. |
| # Note that this is a hard link (ln), not a symlink (ln -s). |
| while ! ln "$lockfile_tmp" "$lockfile" 2>/dev/null; do |
| local lock_pid=$(cat "$lockfile" 2>/dev/null) |
| if [ "$lock_pid" = "$$" ]; then |
| ## We already have the lock, apparently! |
| break |
| fi |
| |
| if [ -n "$lock_pid" ] && ! ps "$lock_pid" >/dev/null; then |
| echo "Removing stale lock. Process PID=$lock_pid, no longer exists." |
| rm "$lockfile" |
| else |
| if [ "$printed_msg" = 0 ]; then |
| echo -n "Waiting for PID $lock_pid to give up the $server lock." |
| printed_msg=1 |
| else |
| echo -n '.' |
| fi |
| sleep 1 |
| fi |
| done |
| |
| if [ "$printed_msg" != 0 ]; then |
| echo |
| fi |
| rm -f "$lockfile_tmp" |
| } |
| |
| function release_lock { |
| SERVER=$1 |
| LOCKFILE=$2 |
| |
| echo "Unlocking $SERVER." |
| rm "$LOCKFILE" |
| } |
| exit_status=0 |
| |
| # Returns the unix system time in seconds. |
| function now_sec() { |
| date +%s |
| } |
| |
| start_time_sec=$(now_sec) |
| |
| # Prints the elapsed time, in seconds, since the last time print_elapsed_time |
| # was called. Any arguments to this function will be passed to through as the |
| # first args to echo. The intent is you can put |
| # print_elapsed_time -n |
| # to allow callers to print more stuff on the same line. |
| function print_elapsed_time() { |
| current_time_sec=$(now_sec) |
| if [ "$previous_time_sec" != 0 ]; then |
| echo -n : "$((current_time_sec - start_time_sec))" sec |
| fi |
| } |
| |
| # Determines whether the passed-in PID is alive. |
| function is_process_alive() { |
| ps "$1" > /dev/null |
| } |
| |
| # Runs command, redirecting stdout+stderr to a logfile, which is specified as |
| # the first argument. The second argument is a string to put in the status |
| # messsage. This might be all or part of the actual command, or something |
| # descriptive. The rest of the arguments are the command. |
| # |
| # The full command will be added as the first line of the logfile. |
| # |
| # This function blocks until the command finishes, but it prints out status |
| # lines at increasing intervals, with the max interval being 60 seconds. Once |
| # the 60-second threshold is reached, each status line is emitted with a |
| # newline. This is so that two long-running commands running in parallel |
| # don't completely overwrite each other's status. |
| # |
| # The global variable 'exit_status' is set to 0 if the command succeeds, 1 if |
| # it fails. |
| function run_noisy_command_showing_log() { |
| logfile="$1" |
| shift |
| description="$1" |
| shift |
| |
| start_time_sec=$(now_sec) |
| previous_time_sec=$start_time_sec |
| echo "$@" "&>" "$logfile" "..." |
| ("$@" ; echo exit_status=$?) &> "$logfile" & |
| pid=$! |
| print_interval_sec=60 |
| while is_process_alive $pid; do |
| sleep 1 |
| current_sec=$(now_sec) |
| interval_sec=$((current_sec - previous_time_sec)) |
| if [ $interval_sec -ge $print_interval_sec ]; then |
| previous_time_sec=$current_sec |
| lines_in_logfile=$(wc -l < "$logfile") |
| echo " ... $description: $lines_in_logfile lines$(print_elapsed_time)" |
| fi |
| done |
| if [ "$(tail -n 1 "$logfile")" = "exit_status=0" ]; then |
| echo -n "PASS" |
| local exit_status=0 |
| else |
| echo -n "FAIL" |
| local exit_status=1 |
| fi |
| print_elapsed_time |
| # shellcheck disable=SC2145 |
| echo " ($@ >& $logfile)" |
| return $exit_status |
| } |