title: bash code take error and how to locate where the error occurred?
body: <p>when I execute this code, taking error &quot;awk: line 19: syntax error at or near&quot;, I want to know how to locate where the error occurred, line 19 is comments, so line 19 is not the 19 line in code? and what can i do for this issue?</p>
  <p>TL;DR
  I have described my problem，but I can't post, &quot;It looks like your post is mostly code; please add some more details.&quot;  I have to write this... TAT</p>
  <pre><code>#!/bin/bash
  #
  # opensnoop - trace open() syscalls with file details.
  #             Written using Linux ftrace.
  #
  # This traces open() syscalls, showing the file name and returned file
  # descriptor number (or -1, for error).
  #
  # This implementation is designed to work on older kernel versions, and without
  # kernel debuginfo. It works by dynamic tracing of the return value of getname()
  # as a string, and associating it with the following open() syscall return.
  # This approach is kernel version specific, and may not work on your version.
  # It is a workaround, and proof of concept for ftrace, until more kernel tracing
  # functionality is available.
  #
  # USAGE: ./opensnoop [-htx] [-d secs] [-p pid] [-L tid] [-n name] [filename]
  #
  # Run &quot;opensnoop -h&quot; for full usage.
  #
  # REQUIREMENTS: FTRACE and KPROBE CONFIG, syscalls:sys_exit_open tracepoint,
  # getname() kernel function (you may already have these on recent kernels),
  # and awk.
  #
  # From perf-tools: https://github.com/brendangregg/perf-tools
  #
  # See the opensnoop(8) man page (in perf-tools) for more info.
  #
  # COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
  #
  #  This program is free software; you can redistribute it and/or
  #  modify it under the terms of the GNU General Public License
  #  as published by the Free Software Foundation; either version 2
  #  of the License, or (at your option) any later version.
  #
  #  This program is distributed in the hope that it will be useful,
  #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  #  GNU General Public License for more details.
  #
  #  You should have received a copy of the GNU General Public License
  #  along with this program; if not, write to the Free Software Foundation,
  #  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  #
  #  (http://www.gnu.org/copyleft/gpl.html)
  #
  # 20-Jul-2014   Brendan Gregg   Created this.
  
  ### default variables
  tracing=/sys/kernel/debug/tracing
  flock=/var/tmp/.ftrace-lock; wroteflock=0
  opt_duration=0; duration=; opt_name=0; name=; opt_pid=0; pid=; opt_tid=0; tid=
  ftext=; opt_time=0; opt_fail=0; opt_file=0; file=
  trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
  
  function usage {
      cat &lt;&lt;-END &gt;&amp;2
      USAGE: opensnoop [-htx] [-d secs] [-p PID] [-L TID] [-n name] [filename]
                       -d seconds      # trace duration, and use buffers
                       -n name         # process name to match on open
                       -p PID          # PID to match on open
                       -L TID          # PID to match on open
                       -t              # include time (seconds)
                       -x              # only show failed opens
                       -h              # this usage message
                       filename        # match filename (partials, REs, ok)
        eg,
             opensnoop                 # watch open()s live (unbuffered)
             opensnoop -d 1            # trace 1 sec (buffered)
             opensnoop -p 181          # trace I/O issued by PID 181 only
             opensnoop conf            # trace filenames containing &quot;conf&quot;
             opensnoop 'log$'          # filenames ending in &quot;log&quot;
  
      See the man page and example file for more info.
  END
      exit
  }
  
  function warn {
      if ! eval &quot;$@&quot;; then
          echo &gt;&amp;2 &quot;WARNING: command failed \&quot;$@\&quot;&quot;
      fi
  }
  
  function end {
      # disable tracing
      echo 2&gt;/dev/null
      echo &quot;Ending tracing...&quot; 2&gt;/dev/null
      cd $tracing
      warn &quot;echo 0 &gt; events/kprobes/getnameprobe/enable&quot;
      warn &quot;echo 0 &gt; events/syscalls/sys_exit_open/enable&quot;
      warn &quot;echo 0 &gt; events/syscalls/sys_exit_openat/enable&quot;
      if (( opt_pid || opt_tid )); then
          warn &quot;echo 0 &gt; events/kprobes/getnameprobe/filter&quot;
          warn &quot;echo 0 &gt; events/syscalls/sys_exit_open/filter&quot;
          warn &quot;echo 0 &gt; events/syscalls/sys_exit_openat/filter&quot;
      fi
      warn &quot;echo -:getnameprobe &gt;&gt; kprobe_events&quot;
      warn &quot;echo &gt; trace&quot;
      (( wroteflock )) &amp;&amp; warn &quot;rm $flock&quot;
  }
  
  function die {
      echo &gt;&amp;2 &quot;$@&quot;
      exit 1
  }
  
  function edie {
      # die with a quiet end()
      echo &gt;&amp;2 &quot;$@&quot;
      exec &gt;/dev/null 2&gt;&amp;1
      end
      exit 1
  }
  
  ### process options
  while getopts d:hn:p:L:tx opt
  do
      case $opt in
      d)  opt_duration=1; duration=$OPTARG ;;
      n)  opt_name=1; name=$OPTARG ;;
      p)  opt_pid=1; pid=$OPTARG ;;
      L)  opt_tid=1; tid=$OPTARG ;;
      t)  opt_time=1 ;;
      x)  opt_fail=1 ;;
      h|?)    usage ;;
      esac
  done
  shift $(( $OPTIND - 1 ))
  if (( $# )); then
      opt_file=1
      file=$1
      shift
  fi
  (( $# )) &amp;&amp; usage
  
  ### option logic
  (( opt_pid + opt_name + opt_tid &gt; 1 )) &amp;&amp; \
      die &quot;ERROR: use at most one of -p, -n, -L.&quot;
  (( opt_pid )) &amp;&amp; ftext=&quot; issued by PID $pid&quot;
  (( opt_tid )) &amp;&amp; ftext=&quot; issued by TID $tid&quot;
  (( opt_name )) &amp;&amp; ftext=&quot; issued by process name \&quot;$name\&quot;&quot;
  (( opt_file )) &amp;&amp; ftext=&quot;$ftext for filenames containing \&quot;$file\&quot;&quot;
  if (( opt_duration )); then
      echo &quot;Tracing open()s$ftext for $duration seconds (buffered)...&quot;
  else
      echo &quot;Tracing open()s$ftext. Ctrl-C to end.&quot;
  fi
  
  ### select awk
  (( opt_duration )) &amp;&amp; use=mawk || use=gawk  # workaround for mawk fflush()
  [[ -x /usr/bin/$use ]] &amp;&amp; awk=$use || awk=awk
  
  ### check permissions
  cd $tracing || die &quot;ERROR: accessing tracing. Root user? Kernel has FTRACE?
      debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)&quot;
  
  ### ftrace lock
  [[ -e $flock ]] &amp;&amp; die &quot;ERROR: ftrace may be in use by PID $(cat $flock) $flock&quot;
  echo $$ &gt; $flock || die &quot;ERROR: unable to write $flock.&quot;
  wroteflock=1
  
  ### setup and begin tracing
  echo nop &gt; current_tracer
  ver=$(uname -r)
  if [[ &quot;$ver&quot; == 2.* || &quot;$ver&quot; == 3.[1-6].* ]]; then
      # rval is char *
      kprobe='r:getnameprobe getname +0($retval):string'
  else
      # rval is struct filename *
      kprobe='r:getnameprobe getname +0(+0($retval)):string'
  fi
  if ! echo $kprobe &gt;&gt; kprobe_events; then
      edie &quot;ERROR: adding a kprobe for getname(). Exiting.&quot;
  fi
  if (( opt_pid )); then
      filter=
      for tid in /proc/$pid/task/*; do
          filter=&quot;$filter || common_pid == ${tid##*/}&quot;
      done
      filter=${filter:3}  # trim leading ' || ' (four characters)
      if ! echo $filter &gt; events/kprobes/getnameprobe/filter || \
          ! echo $filter &gt; events/syscalls/sys_exit_open/filter || \
          ! echo $filter &gt; events/syscalls/sys_exit_openat/filter
      then
          edie &quot;ERROR: setting -p $pid. Exiting.&quot;
      fi
  fi
  if (( opt_tid )); then
      if ! echo &quot;common_pid == $tid&quot; &gt; events/kprobes/getnameprobe/filter || \
          ! echo &quot;common_pid == $tid&quot; &gt; events/syscalls/sys_exit_open/filter || \
          ! echo &quot;common_pid == $tid&quot; &gt; events/syscalls/sys_exit_openat/filter
      then
          edie &quot;ERROR: setting -L $tid. Exiting.&quot;
      fi
  fi
  if ! echo 1 &gt; events/kprobes/getnameprobe/enable; then
      edie &quot;ERROR: enabling kprobe for getname(). Exiting.&quot;
  fi
  if ! echo 1 &gt; events/syscalls/sys_exit_open/enable; then
      edie &quot;ERROR: enabling open() exit tracepoint. Exiting.&quot;
  fi
  if ! echo 1 &gt; events/syscalls/sys_exit_openat/enable; then
      edie &quot;ERROR: enabling openat() exit tracepoint. Exiting.&quot;
  fi
  (( opt_time )) &amp;&amp; printf &quot;%-16s &quot; &quot;TIMEs&quot;
  printf &quot;%-16.16s %-6s %4s %s\n&quot; &quot;COMM&quot; &quot;PID&quot; &quot;FD&quot; &quot;FILE&quot;
  
  #
  # Determine output format. It may be one of the following (newest first):
  #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
  #           TASK-PID    CPU#    TIMESTAMP  FUNCTION
  # To differentiate between them, the number of header fields is counted,
  # and an offset set, to skip the extra column when needed.
  #
  offset=$($awk 'BEGIN { o = 0; }
      $1 == &quot;#&quot; &amp;&amp; $2 ~ /TASK/ &amp;&amp; NF == 6 { o = 1; }
      $2 ~ /TASK/ { print o; exit }' trace)
  
  ### print trace buffer
  warn &quot;echo &gt; trace&quot;
  ( if (( opt_duration )); then
      # wait then dump buffer
      sleep $duration
      cat trace
  else
      # print buffer live
      cat trace_pipe
  fi ) | $awk -v o=$offset -v opt_name=$opt_name -v name=$name \
      -v opt_duration=$opt_duration -v opt_time=$opt_time -v opt_fail=$opt_fail \
      -v opt_file=$opt_file -v file=$file '
      # common fields
      $1 != &quot;#&quot; {
          # task name can contain dashes and space
          split($0, line, &quot;-&quot;)
          sub(/^[ \t\r\n]+/, &quot;&quot;, line[1])
          comm = line[1]
          if (opt_name &amp;&amp; match(comm, name) == 0)
              next
          sub(/ .*$/, &quot;&quot;, line[2])
          pid = line[2]
      }
  
      # do_sys_open()
      $1 != &quot;#&quot; &amp;&amp; $(5+o) ~ /do_sys_open/ {
          #
          # eg: ... (do_sys_open+0xc3/0x220 &lt;- getname) arg1=&quot;file1&quot;
          #
          match($0, /arg1=\&quot;(.+)\&quot;/, m)
          lastfile[pid] = m[1]
      }
  
      # sys_open() / sys_openat()
      $1 != &quot;#&quot; &amp;&amp; ($(4+o) == &quot;sys_open&quot; || $(4+o) == &quot;sys_openat&quot;) {
          filename = lastfile[pid]
          if (!filename)
              next
          delete lastfile[pid]
          if (opt_file &amp;&amp; filename !~ file)
              next
          rval = $NF
          # matched failed as beginning with 0xfffff
          if (opt_fail &amp;&amp; rval !~ /0xfffff/)
              next
          if (rval ~ /0xfffff/)
              rval = -1
  
          if (opt_time) {
              time = $(3+o); sub(&quot;:&quot;, &quot;&quot;, time)
              printf &quot;%-16s &quot;, time
          }
          printf &quot;%-16.16s %-6s %4s %s\n&quot;, comm, pid, rval, filename
      }
  
      $0 ~ /LOST.*EVENTS/ {
          delete lastfile
          print &quot;WARNING: &quot; $0 &gt; &quot;/dev/stderr&quot; }
  '
  
  ### end tracing
  end
  </code></pre>