i have a bash script that shows "Segment Violation" on line
sp-sc-auth "${sopUrl}" 8809 8908 > /dev/null &
but when sp-sc-auth is executed from terminal works fine
I set:
set -o pipefail
set -o errexit
set -o xtrace
set -o nounset
end script continue executing but throws that "Segment Violation" error...
System is a debian 64 bits
Thanks in advance
Regars
The ugly code:
#!/usr/bin/env bash
# Init
set -o pipefail
set -o errexit
#set -o xtrace
set -o nounset
__DIR__="$(cd "$(dirname "${0}")"; echo $(pwd))"
__BASE__="$(basename "${0}")"
__FILE__="${__DIR__}/${__BASE__}"
ARG1="${1:-Undefined}"
display_usage() {
scriptName=$(basename $0)
echo -e "Uso:\n "${scriptName}" [6,7,8,9,10 o 12]"
echo "Sin especificar el canal, búsqueda de retransmisiones"
}
parse_arenavision() {
url="http://www.arenavision.in/agenda"
if ! av=$(curl -s "${url}");then
echo "Sin conexión"
exit 1
fi
started="off"
declare -a _list
element=""
while read line
do
if [[ $line =~ (([0-9][0-9]+/[0-9]+/[0-9]+.*)) ]]; then
element=$(echo "${BASH_REMATCH[0]}" | sed -r 's#CET|AV([^6789]|1[02])##g; s#<br />##g; s#//|&.*;##g; s#/\s*$##g; s#INGLATERRA/PREMIER LEAGUE#PREMIER#g; s#ITALIA/SERIE A#SERIE A#g; s#ITALIA/SERIE A#SERIE A#g;' | tr -dc '[:print:]')
if [[ "${element}" =~ (.*AV[6789]|.*AV10|.*AV12) ]]; then
_list+=("${element}")
fi
started="on"
else
if [[ ${started} == "on" ]]; then
break
fi
fi
done <<< "${av}"
for i in "${_list[#]}"; do
if [[ "${i}" =~ (.*BALONCESTO.*) ]]; then
echo -e "\e[92m${i}\e[0m"
elif [[ "${i}" =~ (.*LIGA BBVA.*) ]]; then
echo -e "\e[37m${i}\e[0m"
else
echo "${i}"
fi
done
}
case $ARG1 in
"Undefined" )
parse_arenavision
exit 0
;;
[6789] )
page="${ARG1}"
;;
10 )
page="${ARG1}"
;;
* )
display_usage
exit 1
;;
esac
# Delete "zombies"
if pgrep -f "sp-sc"
then
kill -9 `pgrep -f "sp-sc-auth"`
fi
url="http://www.arenavision.in/arenavision$page"
# Get url content and url sop
if ! content=$(curl -s "${url}");then
echo "Sin conexión"
fi
if [[ $content =~ (sop://([A-Za-z0-9_]+|\.)+:[0-9]+) ]]; then
sopUrl=${BASH_REMATCH[1]}
else
echo "No se ha encontrado la url"
exit 1
fi
# Connect ArenaVision 1
children=""
trap 'kill $children 1>/dev/null 2>&1; exit 143' EXIT
sp-sc-auth "${sopUrl}" 8809 8908 > /dev/null &
children="$!"
# Check if exists
line='[ ]'
for i in {0..15}
do
replace="${line/ /#}"
line=$replace
echo -ne "Comprobando sopcast ${replace}" \\r
sleep 1
done
echo -ne "\033[2K"
if ! kill -0 "${children}" 1>/dev/null 2>&1; then
echo "Sin emisión"
exit 1
else
echo -ne "Comprobando sopcast [ OK ]" \\r
echo
fi
# Open VLC player
line='[ ]'
for i in {0..25}
do
replace="${line/ /#}"
line=$replace
echo -ne "Cargando reproductor ${replace}" \\r
sleep 1
done
if ! kill -0 "${children}" 1>/dev/null 2>&1; then
echo "Fallo en recepción"
exit 1
else
vlc http://localhost:8908/tv.asf 1>/dev/null 2>&1
echo -ne "\033[2K"
fi
exit 0
errexit cannot work on programs run in the background, so this is unsurprising -- the inline command is simply starting a background process, and that (starting a background process) succeeds, even if the process itself subsequently fails.
If you call wait $! subsequently, then errexit will be able to take effect, as the wait call will exit with the exit status of the program itself. (Of course, if you can call wait $!, then this raises the question of why you were backgrounding the initial program to start with).
If you always want to kill the parent script if the child fails, you can do this instead:
(sp-sc-auth "$sopUrl" 8809 8908 >/dev/null || kill $$) &
$$ evaluates to the PID of the parent shell, not the subshell, so this will act accordingly.
As for the segfault itself, "program X segfaults" is a question too vague to be addressed here. To even start debugging that, you'd need to collect the core dump created on its failure (enabling cores if necessary), install debug symbols for sopcast, and use gdb to collect a stack trace from the core file created on failure.
Related
I have a pretty simple bash script that coordinates running a couple python scripts. What I am having trouble figuring out is why after running the bash script (. bash_script.sh), the terminal hangs. I can't ctrl+c, ctrl+z or do anything except restart the SSH session. All I see is just a blinking cursor. Checking all the log files indicates a 0 status exit code with no errors in the scripts themselves. Running ps aux | grep bash_script.sh does not show any anything running either. Is there anyway to debug this?
#!/bin/bash
exec >> <DIR>/logfile.log 2>&1
script_message () {
status_arg=$1
if [[ $status_arg = "pass" ]]; then
printf "Script Done\n"
printf '=%.0s' {1..50}
printf "\n"
elif [[ $status_arg = "fail" ]]; then
printf "Script Failed\n"
printf '=%.0s' {1..50}
printf "\n"
else
:
fi
}
current_date=$(date '+%Y-%m-%d %H:%M:%S')
day=$(date +%u)
hour=$(date +%H)
printf "RUN DATE: $current_date\n"
# activate virtual env
source /<VENV DIR/bin/activate>
python <PYTHON SCRIPT>.py >> <DIR>/logfile2.log 2>&1
retVal=$?
if [[ $retVal -eq 0 && $day -eq 4 ]]; then
python <PYTHON SCRIPT 2>.py >> <DIR>/logfile3.log 2>&1
script_message pass
elif [[ $retVal -eq 0 ]]; then
script_message pass
else
#:
script_message fail
fi
echo $?
I'm trying to do a script that does things on my linux computer but does not respects wait commands.
That's my code that does not work
cat file.txt | while read line || [[ -n $line ]]; do
do
QUEST="$(./fi $line | grep -oE " fi " &> A.txt; echo $? >"$dir")" & proc=$!
wait "$proc"
read ret <"$dir"
if [[ "$QUEST" != "" ]];then echo "$line" &>> A.txt; fi; unset QUEST;
done &> /dev/null & wait
It have to do one quest a time and save the output (that could exists or not).
When you run a command in the background, it's run in a subshell. Any variable assignments are not visible in the original shell, so the assignment to QUEST doesn't work.
You don't need to do that in the background, since you're immediately waiting for the command to finish. Just run it normally.
while read line || [[ -n $line ]]; do
do
QUEST="$(./fi $line | grep -oE " fi " &> A.txt)"
ret=$?
if [[ "$QUEST" != "" ]]
then echo "$line" &>> A.txt
fi
done &> /dev/null < file.txt
unset QUEST
There's also no need to write $? to $dir. The exit status of a variable assignment from a command substitution is the exit status of the command.
I've been following a tutorial on connecting a raspberry pi to the AWS greengrass and I keep getting a segmentation fault on the final step. AWS provided me with this greengrassd shell script however when i run it I'm getting a segmentation fault. I have no idea why its throwing this error so any help would be appreciated.
AWS Greengrass Tutorial / RaspberryPi
Error
pi#raspberrypi:/greengrass/ggc/packages/1.1.0 $ sudo ./greengrassd start
Setting up greengrass daemon
Validating execution environment
Found cgroup subsystem: cpu
Found cgroup subsystem: cpuacct
Found cgroup subsystem: blkio
Found cgroup subsystem: memory
Found cgroup subsystem: devices
Found cgroup subsystem: freezer
Found cgroup subsystem: net_cls
Starting greengrass daemon./greengrassd: line 158: 2254 Segmentation fault nohup $COMMAND > /dev/null 2> $CRASH_LOG < /dev/null
Greengrass daemon 2254 failed to start
greengrassd script
#!/usr/bin/env bash
##########Environment Requirement for Greengrass Daemon##########
# by default, the daemon assumes it's going to be launched from a directory
# that has the following structure:
# GREENGRASS_ROOT/
# greengrassd
# bin/daemon
# configuration/
# group/group.json
# certs/server.crt
# lambda/
# system_lambda1/...
# system_lambda2/...
# root cgroup has to be mounted separately, this script doesn't do that for you.
#################################################################
set -e
PWD=$(cd $(dirname "$0"); pwd)
GGC_PKG_HOME=$(readlink -f $PWD)
GG_HOME=$(cd $GGC_PKG_HOME/../../; pwd)
CRASH_LOG=$GG_HOME/var/log/crash.log
GGC_ROOT_FS=$GGC_PKG_HOME/ggc_root
PID_FILE=/var/run/greengrassd.pid
FS_SETTINGS=/proc/sys/fs
GGC_GROUP=ggc_group
GGC_USER=ggc_user
MAX_DAEMON_KILL_WAIT_SECONDS=60
RETRY_SIGTERM_INTERVAL_SECONDS=20
if [ -z "$COMMAND" ]; then
COMMAND="$GGC_PKG_HOME/bin/daemon -core-dir=$GGC_PKG_HOME -greengrassdPid=$$"
fi
# Function ran as part of initial setup
setup() {
echo "Setting up greengrass daemon"
mkdir -p $GGC_ROOT_FS
# Mask greengrass directory for containers
mknod $GGC_ROOT_FS/greengrass c 1 3 &>/dev/null || true
mkdir -p $(dirname "$CRASH_LOG")
}
validatePlatformSecurity() {
if [[ -f $FS_SETTINGS/protected_hardlinks &&
-f $FS_SETTINGS/protected_symlinks ]]; then
PROT_HARDLINK_VAL=$(cat $FS_SETTINGS/protected_hardlinks)
PROT_SOFTLINK_VAL=$(cat $FS_SETTINGS/protected_symlinks)
if [[ "$PROT_HARDLINK_VAL" -ne 1 || "$PROT_SOFTLINK_VAL" -ne 1 ]]; then
echo "AWS Greengrass detected insecure OS configuration: No hardlink/softlink protection enabled." | tee -a $CRASH_LOG
exit 1
fi
fi
}
validateEnvironment() {
echo "Validating execution environment"
# ensure all commands that the installation script is going to use are available
if ! type grep >/dev/null ; then
echo "grep command is NOT on the path or is NOT installed on the system"
exit 1
fi
if ! type cat >/dev/null ; then
echo "cat command is NOT on the path or is NOT installed on the system"
exit 1
fi
if ! type awk >/dev/null ; then
echo "awk command is NOT on the path or is NOT installed on the system"
exit 1
fi
if ! type id >/dev/null ; then
echo "id command is NOT on the path or is NOT installed on the system"
exit 1
fi
if ! type ps >/dev/null ; then
echo "ps command is NOT on the path or is NOT installed on the system"
exit 1
fi
if ! type sqlite3 >/dev/null ; then
echo "sqlite3 command is NOT on the path or is NOT installed on the system"
exit 1
fi
# the script needs to be run as root
if [ ! $(id -u) = 0 ]; then
echo "The script needs to be run using sudo"
exit 1
fi
if ! id $GGC_USER >/dev/null ; then
echo "${GGC_USER} doesn't exist. Please add a user ${GGC_USER} on the system"
exit 1
fi
if ! grep -q $GGC_GROUP /etc/group ; then
echo "${GGC_GROUP} doesn't exist. Please add a group ${GGC_GROUP} on the system"
exit 1
fi
# ensure that kernel supports cgroup
if [ ! -e /proc/cgroups ]; then
echo "The kernel in use does NOT support cgroup."
exit 1
fi
# assume that all kernel supported subsystems, which are listed in /proc/cgroups, are going to be used
# so check whether all of them are mounted.
for d in `awk '$4 == 1 {print $1}' /proc/cgroups`; do
if cat /proc/self/cgroup | grep -q $d; then
echo "Found cgroup subsystem: $d"
else
# exit with error if can't find cgroup
echo "The cgroup subsystem is not mounted: $d"
exit 1
fi
done
}
finish() {
pid=$1
echo "$pid" > $PID_FILE
echo ""
echo -e "\e[0;32mGreengrass successfully started with PID: $pid\e[0m"
exit 0
}
start() {
setup
if [[ $INSECURE -ne 1 ]]; then
validatePlatformSecurity
fi
validateEnvironment
trap 'finish $pid' SIGUSR1
echo ""
echo -n "Starting greengrass daemon"
if nohup $COMMAND >/dev/null 2>$CRASH_LOG < /dev/null &
then
pid=$!
# sleep 10 seconds to wait for daemon to start or exit
sleep 10 &
wait $!
echo ""
echo "Greengrass daemon $pid failed to start"
echo -e "\e[0;31m$(cat $CRASH_LOG)\e[0m"
exit 1
else
echo "Failed to start Greengrass daemon"
exit 1
fi
}
version() {
$GGC_PKG_HOME/bin/daemon --version
}
stop() {
if [ -f $PID_FILE ]; then
PID=$(cat $PID_FILE)
echo "Stopping greengrass daemon of PID: $PID"
if [ ! -e "/proc/$PID" ]; then
rm $PID_FILE
echo "Process with pid $PID does not exist already"
return 0
fi
echo -n "Waiting"
kill "$PID" > /dev/null 2>&1
total_sleep_seconds=0
until [ "$total_sleep_seconds" -ge "$MAX_DAEMON_KILL_WAIT_SECONDS" ]; do
sleep 1
# If the pid no longer exists, we're done, remove the pid file and exit. Otherwise, just increment the loop counter
if [ ! -e "/proc/$PID" ]; then
rm $PID_FILE
echo -e "\nStopped greengrass daemon, exiting with success"
break
else
total_sleep_seconds=$(($total_sleep_seconds+1))
echo -n "."
fi
# If it has been $RETRY_SIGTERM_INTERVAL_SECONDS since the last SIGTERM, send SIGTERM
if [ $(($total_sleep_seconds % $RETRY_SIGTERM_INTERVAL_SECONDS)) -eq "0" ]; then
kill "$PID" > /dev/null 2>&1
fi
done
if [ $total_sleep_seconds -ge $MAX_DAEMON_KILL_WAIT_SECONDS ] && [ -e "/proc/$PID" ]; then
# If we are here, we never exited in the previous loop and the pid still exists. Exit with failure.
kill -9 "$PID" > /dev/null 2>&1
echo -e "\nProcess with pid $PID still alive after timeout of $MAX_DAEMON_KILL_WAIT_SECONDS seconds. Forced kill process, exiting with failure."
exit 1
fi
fi
}
usage() {
echo ""
echo "Usage: $0 [FLAGS] {start|stop|restart}"
echo ""
echo -e "[FLAGS]: \n -i, --insecure \t Run GGC in insecure mode without hardlink/softlink protection, (highly discouraged for production use) \n -v, --version \t\t Outputs the version of GGC."
echo ""
exit 1
}
if [[ $# -eq 0 ]]; then
usage
fi
for var in "$#"
do
case "$var" in
-v|--version)
version
exit 0
;;
esac
done
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-i|--insecure)
mkdir -p $(dirname "$CRASH_LOG")
echo "Warning! You are running in insecure mode, this is highly discouraged!" | tee -a $CRASH_LOG
INSECURE=1
;;
-h|--help)
usage
;;
start)
stop
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
usage
esac
shift
done
#Jim Maybe check the model of Pi you are using?
It seems that the Pi version of Greengrass is for ARMv7-A. I got this problem too and I'm using an older Model 1 B+ which is ARMv6Z (https://en.wikipedia.org/wiki/Raspberry_Pi#Specifications).
The error we're seeing for line 158 is the ./greengrassd script waiting for the actual process to run:
sudo /greengrass/ggc/packages/1.1.0/bin/daemon -core-dir=/greengrass/ggc/packages/1.1.0 -greengrassdPid=641
/greengrass/ggc/packages/1.1.0/bin/daemon is the binary. If you run the above command directly in the console it exits with the same segmentation fault error.
AWS do recommend using the Pi 3 so I'm guessing it will work on that.
have some problem with shell script.
In our office we set up only few commands, that available for devs when they are trying ssh to server. It is configured with help of .ssh/authorized_keys file and available command for user there is bash script:
#!/bin/sh
if [[ $1 == "--help" ]]; then
cat <<"EOF"
This script has the purpose to let people remote execute certain commands without logging into the system.
For this they NEED to have a homedir on this system and uploaded their RSA public key to .ssh/authorized_keys (via ssh-copy-id)
Then you can alter that file and add some commands in front of their key eg :
command="/usr/bin/dev.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
The user will do the following : ssh testuser#server tail testserver.example.com/2017/01/01/user.log
EOF
exit 0;
fi
# set global variable
set $SSH_ORIGINAL_COMMAND
# set the syslog path where the files can be found
PATH="/opt/syslog/logs"
# strip ; or any other unwanted signs out of the command, this prevents them from breaking out of the setup command
if [[ $1 != "" ]]; then
COMMAND=$1
COMMAND=${COMMAND//[;\`]/}
fi
if [[ $2 != "" ]]; then
ARGU1=$2
ARGU1=${ARGU1//[;\`]/}
fi
if [[ $3 != "" ]]; then
ARGU2=$3
ARGU2=${ARGU2//[;\`]/}
fi
if [[ $4 != "" ]]; then
ARGU3=$4
ARGU3=${ARGU3//[;\`]/}
fi
# checking for the commands
case "$COMMAND" in
less)
ARGU2=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
exit 1;
fi
#echo " --------------------------------- LESS $FILE"
/usr/bin/less $FILE
;;
grep)
if [[ $ARGU2 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
if [[ $ARGU1 == "" ]]; then
echo "Pls give a string to search for"
exit 1
fi
ARGU2=${ARGU2//\.\./}
FILE=$PATH/$ARGU2
/usr/bin/logger -t restricted-command -- "------- $USER Executing grep $ARGU1 \"$ARGU2\" $FILE"
if [ ! -f $FILE ]; then
echo "File doesn't exist"
/usr/bin/logger -t restricted-command -- "$USER Executing $#"
exit 1;
fi
/bin/grep $ARGU1 $FILE
;;
tail)
if [[ $ARGU1 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
ARGU1=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
/usr/bin/logger -t restricted-command -- "$USER Executing $# ($FILE)"
exit 1;
fi
/usr/bin/tail -f $FILE
;;
cat)
ARGU2=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
exit 1;
fi
/bin/cat $FILE
;;
help)
/bin/cat <<"EOF"
# less LOGNAME (eg less testserver.example.com/YYYY/MM/DD/logfile.log)
# grep [ARGUMENT] LOGNAME
# tail LOGNAME (eg tail testserver.example.com/YYYY/MM/DD/logfile.log)
# cat LOGNAME (eg cat testserver.example.com/YYYY/MM/DD/logfile.log)
In total the command looks like this : ssh user#testserver.example.com COMMAND [ARGUMENT] LOGFILE
EOF
/usr/bin/logger -t restricted-command -- "$USER HELP requested $#"
exit 1
;;
*)
/usr/bin/logger -s -t restricted-command -- "$USER Invalid command $#"
exit 1
;;
esac
/usr/bin/logger -t restricted-command -- "$USER Executing $#"
The problem is next:
when i try to exec some command, it takes only first argument, if i do recursion in files by using {n,n1,n2} - it doesn't work:
[testuser#local ~]$ ssh testuser#syslog.server less srv1838.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
0
[testuser#local ~]$ ssh testuser#syslog.server less srv2010.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
11591
[testuser#local ~]$ ssh testuser#syslog.server less srv{1838,2010}.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
0
[testuser#local ~]$ ssh testuser#syslog.server less srv{2010,1838}.example.com/2017/02/21/local1.log |grep 'srv2010' | wc -l
11591
Could someone help me, how can i parse\count command arguments to make it work?
Thank you and have a nice day!
The number of arguments for a bash script would be $#. As a quick example:
#!/bin/bash
narg=$#
typeset -i i
i=1
while [ $i -le $narg ] ; do
echo " $# $i: $1"
shift
i=$i+1
done
gives, for bash tst.sh a b {c,d}
4 1: a
3 2: b
2 3: c
1 4: d
In your script, the command to execute (cat, less, ...) gets explicitly only the second argument to the script. If you want to read all arguments, you should do something like this (note: only a hint, removed all sorts of checks etc..)
command="$1"
shift
case $command in
(grep) pattern="$1"
shift
while [ $# -gt 0 ] ; do
grep "$pattern" "$1"
shift
done
;;
esac
note: added some quotes as comment suggested, but, being only a hint, you should carefully look at quoting and your checks in your own script.
Less command working now:
case "$COMMAND" in
less)
if [[ $ARGU1 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
FILES_LIST=${#:2}
FILE=(${FILES_LIST//\.\./})
for v in "${FILE[#]}";do
v=${v//[;\']/}
if [ ! -f $v ]; then
echo "File doesn't exist"
fi
/usr/bin/less $PATH/$v
done;;
tail command works too with 2 and more files, but i can't execute tail -f command on two files unfortunately.
So, the idea is to have a script that tries to run a command, and if the command fails it shows up any warnings/errors. My try:
$ cat try.sh
#! /bin/sh
tempfile=`tempfile 2>/dev/null` || tempfile=/tmp/temp$$
trap 'rm -f $tempfile >/dev/null 2>&1' 0
trap 'exit 2' 1 2 3 15
echo "$#"
if ! "$#" >$tempfile 2>&1; then
cat $tempfile;
false;
fi
Do you think that this script is ok (wrt portability and functionality)?
Some changes I would make:
Use "$#" as Steve Emmerson suggested
Don't redirect stdout of tempfile to /dev/null; that's what you're trying to capture in the variable!
Consider mktemp; it is more portable.
Capture and exit with actual exit code of command, so information is not lost.
E.g., without error checks,
tempfile=`mktemp 2>/dev/null || echo /tmp/tempfile$$`
[ -w "$tempfile" ] || { echo "Can't make tempfile" >&2; exit 1; }
"$#" 2> $tempfile
rc=$?
case $rc in
0) ;;
*) cat "$tempfile" >&2 ;;
esac
rm -f "$tempfile"
exit $rc
I would enclose the $# in double quotes in the "if" statement in order to preserve word boundaries.