<p>Joshua C. Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/10832">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Joshua C. Colp: Looks good to me, but someone else must approve; Approved for Submit
George Joseph: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ast_coredumper: Refactor the pid determination process<br><br>In order to get a dump of the running process, we need to find the<br>pid of the main asterisk process. This can be tricky if there are<br>also instances of "asterisk -r" running or if an alternate location<br>for asterisk.conf was specified on the command line with the -C<br>option that also specified an alternation location for the pid file.<br><br>So now...<br><br>1. We find the asterisk executable with "which" or the --asterisk-bin<br> command line option.<br>2. If there's only 1 process with an executable path that matches,<br> we use that pid. If not...<br>3. We try "<asterisk-bin> -rx 'core show settings'" and parse the<br> output to find the pidfile, then read that for the pid. If that<br> didn't work...<br>4. We get a list of all the pids matching <asterisk-bin> and look<br> in /proc/<pid>/cmdline for a -C argument and retry the "core show<br> settings" using the same -C option. We can't parse the output<br> of "ps" to get the -C path because it may contain spaces. The<br> contents of /proc/<pid>/cmdline are delimited by NULLs. For BSDs<br> we may have to mount /proc first. :(<br><br>ASTERISK-28221<br>Reported by: Andrew Nagy<br><br>Change-Id: I8aa1f3f912f949df2b5348908803c636bde1d57c<br>---<br>M contrib/scripts/ast_coredumper<br>1 file changed, 84 insertions(+), 29 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/contrib/scripts/ast_coredumper b/contrib/scripts/ast_coredumper</span><br><span>index 0215edb..defb629 100755</span><br><span>--- a/contrib/scripts/ast_coredumper</span><br><span>+++ b/contrib/scripts/ast_coredumper</span><br><span>@@ -372,42 +372,97 @@</span><br><span> # Timestamp to use for output files</span><br><span> df=${tarball_uniqueid:-$(${DATEFORMAT})}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-if [ -z "$asterisk_bin" ]; then</span><br><span style="color: hsl(120, 100%, 40%);">+if [ x"$asterisk_bin" = x ]; then</span><br><span> asterisk_bin=$(which asterisk)</span><br><span> fi</span><br><span> </span><br><span> if $running || $RUNNING ; then</span><br><span> # We need to go through some gyrations to find the pid of the running</span><br><span> # MAIN asterisk process and not someone or something running asterisk -r.</span><br><span style="color: hsl(0, 100%, 40%);">- # The pid file may NOT be in /var/run/asterisk so we need to find any</span><br><span style="color: hsl(0, 100%, 40%);">- # running asterisk process and see if -C was specified on the command</span><br><span style="color: hsl(0, 100%, 40%);">- # line. The chances of more than 1 asterisk instance running with</span><br><span style="color: hsl(0, 100%, 40%);">- # different -C options is so unlikely that we're going to ignore it.</span><br><span style="color: hsl(0, 100%, 40%);">- #</span><br><span style="color: hsl(0, 100%, 40%);">- # 'ps axo command' should work on Linux (back to CentOS6) and FreeBSD.</span><br><span style="color: hsl(0, 100%, 40%);">- # If asterisk was started with -C, get the asterisk.conf file.</span><br><span style="color: hsl(0, 100%, 40%);">- # If it wasn't, assume /etc/asterisk/asterisk.conf</span><br><span style="color: hsl(0, 100%, 40%);">- astetcconf=`ps axo command | sed -n -r -e "s/.*asterisk\s+.*-C\s+([^ ]+).*/\1/gp" | tail -1`</span><br><span style="color: hsl(0, 100%, 40%);">- [ x$astetcconf = x ] && astetcconf=/etc/asterisk/asterisk.conf</span><br><span style="color: hsl(0, 100%, 40%);">- # Now parse out astrundir and cat asterisk.pid</span><br><span style="color: hsl(0, 100%, 40%);">- astrundir=$(sed -n -r -e "s/astrundir\s+[=>]+\s+(.*)/\1/gp" $astetcconf)</span><br><span style="color: hsl(0, 100%, 40%);">- pid=$(cat $astrundir/asterisk.pid 2>/dev/null || : )</span><br><span style="color: hsl(0, 100%, 40%);">- if [ x$pid = x ] ; then</span><br><span style="color: hsl(0, 100%, 40%);">- echo "Asterisk is not running"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ unset pid</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Simplest case first...</span><br><span style="color: hsl(120, 100%, 40%);">+ pids=$(pgrep -f "$asterisk_bin")</span><br><span style="color: hsl(120, 100%, 40%);">+ pidcount=$(echo $pids | wc -w)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ $pidcount -eq 0 ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ >&2 echo "Asterisk is not running"</span><br><span style="color: hsl(120, 100%, 40%);">+ exit 1</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Single process, great.</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ $pidcount -eq 1 ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ pid=$pids</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Found a single asterisk instance running as process $pid"</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # More than 1 asterisk process running</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$pid" = x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ # More than 1 process running, let's try asking asterisk for it's</span><br><span style="color: hsl(120, 100%, 40%);">+ # pidfile</span><br><span style="color: hsl(120, 100%, 40%);">+ pidfile=$("$asterisk_bin" -rx "core show settings" 2>/dev/null | sed -n -r -e "s/^\s*pid file:\s+(.*)/\1/gpi")</span><br><span style="color: hsl(120, 100%, 40%);">+ # We found it</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$pidfile" != x -a -f "$pidfile" ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ pid=$(cat "$pidfile")</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Found pidfile $pidfile with process $pid"</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # It's possible that asterisk was started with the -C option which means the</span><br><span style="color: hsl(120, 100%, 40%);">+ # control socket and pidfile might not be where we expect. We're going to</span><br><span style="color: hsl(120, 100%, 40%);">+ # have to parse the process arguments to see if -C was specified.</span><br><span style="color: hsl(120, 100%, 40%);">+ # The first process that has a -C argument determines which config</span><br><span style="color: hsl(120, 100%, 40%);">+ # file to use to find the pidfile of the main process.</span><br><span style="color: hsl(120, 100%, 40%);">+ # NOTE: The ps command doesn't quote command line arguments that it</span><br><span style="color: hsl(120, 100%, 40%);">+ # displays so we need to look in /proc/<pid>/cmdline.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$pid" = x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ # BSDs might not mount /proc by default :(</span><br><span style="color: hsl(120, 100%, 40%);">+ mounted_proc=0</span><br><span style="color: hsl(120, 100%, 40%);">+ if uname -o | grep -qi "bsd" ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ if ! mount | grep -qi "/proc" ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Temporarily mounting /proc"</span><br><span style="color: hsl(120, 100%, 40%);">+ mounted_proc=1</span><br><span style="color: hsl(120, 100%, 40%);">+ mount -t procfs proc /proc</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for p in $pids ; do</span><br><span style="color: hsl(120, 100%, 40%);">+ # Fields in cmdline are delimited by NULLs</span><br><span style="color: hsl(120, 100%, 40%);">+ astetcconf=$(sed -n -r -e "s/.*\x00-C\x00([^\x00]+).*/\1/gp" /proc/$p/cmdline)</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$astetcconf" != x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ pidfile=$("$asterisk_bin" -C "$astetcconf" -rx "core show settings" 2>/dev/null | sed -n -r -e "s/^\s*pid file:\s+(.*)/\1/gpi")</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$pidfile" != x -a -f "$pidfile" ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ pid=$(cat "$pidfile")</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Found pidfile $pidfile the hard way with process $pid"</span><br><span style="color: hsl(120, 100%, 40%);">+ break</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+ done</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ $mounted_proc -eq 1 ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Unmounting /proc"</span><br><span style="color: hsl(120, 100%, 40%);">+ umount /proc</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$pid" = x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ >&2 echo "Can't determine pid of the running asterisk instance"</span><br><span style="color: hsl(120, 100%, 40%);">+ exit 1</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if $RUNNING ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ answer=Y</span><br><span> else</span><br><span style="color: hsl(0, 100%, 40%);">- if $RUNNING ; then</span><br><span style="color: hsl(0, 100%, 40%);">- answer=Y</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- read -p "WARNING: Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved. Do you wish to continue? (y/N) " answer</span><br><span style="color: hsl(0, 100%, 40%);">- fi</span><br><span style="color: hsl(0, 100%, 40%);">- if [[ "$answer" =~ ^[Yy] ]] ; then</span><br><span style="color: hsl(0, 100%, 40%);">- cf="${OUTPUTDIR:-/tmp}/core-asterisk-running-$df"</span><br><span style="color: hsl(0, 100%, 40%);">- echo "Dumping running asterisk process to $cf"</span><br><span style="color: hsl(0, 100%, 40%);">- ${GDB} ${asterisk_bin} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1</span><br><span style="color: hsl(0, 100%, 40%);">- COREDUMPS+=("$cf")</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- echo "Skipping dump of running process"</span><br><span style="color: hsl(0, 100%, 40%);">- fi</span><br><span style="color: hsl(120, 100%, 40%);">+ read -p "WARNING: Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved. Do you wish to continue? (y/N) " answer</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span style="color: hsl(120, 100%, 40%);">+ if [[ "$answer" =~ ^[Yy] ]] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+ cf="${OUTPUTDIR:-/tmp}/core-asterisk-running-$df"</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Dumping running asterisk process to $cf"</span><br><span style="color: hsl(120, 100%, 40%);">+ ${GDB} ${asterisk_bin} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1</span><br><span style="color: hsl(120, 100%, 40%);">+ COREDUMPS+=("$cf")</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Skipping dump of running process"</span><br><span> fi</span><br><span> fi</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10832">change 10832</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10832"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I8aa1f3f912f949df2b5348908803c636bde1d57c </div>
<div style="display:none"> Gerrit-Change-Number: 10832 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation (1000185) </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua C. Colp <jcolp@digium.com> </div>