FreePBX: 10.13.66-12/ISO install
Asterisk: 13.12.2
asterisk-addons: Latest
Users reported not being able to see/download on demand recordings from the UCP. The calls are however being recorded, /var/spool/asterisk/monitor is full of files, files that should have been moved to the appropriate date directories.
e.g. 2016/12/15.
I have setup a Post Call Recording Script that is set in FreePBX, this also doesn't run. It is simply to see if it ever gets called, appends to a file.
-rw-rw-r-- 1 asterisk asterisk 120364 Dec 15 17:20 1481858418.2722.wav
-rw-r--r-- 1 asterisk asterisk 147884 Dec 16 10:02 1481918523.4964.wav
The top file permissions were changed after running fwconsole chown. This leads me to think that asterisk doesn't have the correct permissions.
This is the breakdown of the debug log for MixMonitor
[2016-12-15 17:03:14] VERBOSE[20476] app_mixmonitor.c: Begin MixMonitor Recording SIP/200-00000125
[2016-12-15 17:03:24] VERBOSE[20476] app_mixmonitor.c: MixMonitor close filestream (mixed)`
[2016-12-15 17:03:24] VERBOSE[20476] app_mixmonitor.c: End MixMonitor Recording SIP/200-00000125
[2016-12-15 17:03:24] VERBOSE[20476] app_mixmonitor.c: Copying recordings for Mixmonitor SIP/200-00000125 to voicemail recipients
[2016-12-15 17:03:24] WARNING[20476] format_wav.c: Unable to set write file size
I have tried changing permissions, re-installing the asterisk-addons, and many other things. Any ideas out there?
Answering my own question.
This is an issue with digium phones and freepbx. Digium uses their own technique to record and save calls. https://wiki.asterisk.org/wiki/display/DIGIUM/Phone+Features+by+Environment
There is a solution to have the calls show up in the CDR and User Portal, but involves changes to the system. Use at you own risk.
Create an executable script belonging to the asterisk user, I keep mine in the asterisk user home directory.
#!/bin/bash
#this script is run from an incrontab
MONITOR=/var/spool/asterisk/monitor/
if [ -d "$MONITOR$1" ]; then
exit
fi
if [ ! -f "$MONITOR$1" ]; then
echo "$(date): Failed to move a recording. \"$MONITOR$1\" does not exist." >> /var/log/asterisk/moved_recording_log
exit
fi
filename=$1
uid=${filename%.*}
if [ $(sed -e "s/^.wav//I" <<< "${filename##*.}") != "wav" ]; then
exit
fi
CONF=/etc/asterisk/res_odbc_additional.conf
user=$(awk -F"=>" '/username=>/ {print $2}' ${CONF})
password=$(awk -F"=>" '/password=>/ {print $2}' ${CONF})
db=$( mysql asteriskcdrdb -u $user -p$password -se "SELECT cnum, calldate as date FROM cdr WHERE uniqueid = \"$uid\";" 2>/dev/null )
ext=$(echo $db | awk '{print $1}')
read -r -a dbd <<< "$db"
IFS="-" read -r -a dbdate <<< "${dbd[1]}"
if [ -z "${dbdate[0]}" ] || [ -z "${dbdate[1]}" ] || [ -z "${dbdate[2]}" ]; then
exit
fi
dir="/var/spool/asterisk/monitor/${dbdate[0]}/${dbdate[1]}/${dbdate[2]}/"
mkdir -p $dir
name="ondemand-${dbd[0]}-${dbd[0]}-${dbdate[0]}${dbdate[1]}${dbdate[2]}-${dbd[2]//:}-$filename"
db=$(mysql asteriskcdrdb -u $user -p$password -se "UPDATE cdr SET recordingfile=\"$name\" WHERE uniqueid = \"$uid\";")
mv $MONITOR$filename $dir$name
exit
The next step is what watches the recordings directory for any files that have been written.
As the asterisk user edit incrontab
incrontab -e
add the following with the location and name of the above script
/var/spool/asterisk/monitor/ IN_CLOSE_WRITE /bin/bash /home/asterisk/move_recordings.sh $#
This is based on a pretty generic FreePBX setup. There may be a nicer way to do this, but this has been working for me.
Correct solution - write file in place where it should be, i.e it to 2016/12/15
It is impossible guess what you dooing wrong(no scripts provided, config etc), but i can suggest you have selinux or permission issue.
Can someone help me to write the Unxi Script to check for the file ABC.txt in FTP location and give result as "Ok" or "No File" . The result "Ok" or "No File" should be written in File XYZ.
Regards,
Sriram
If i understand your question right :
#!/bin/bash
ls -l ABC.txt > temp.txt
wc -l temp.txt > temp2.txt
some_var=$(sed 's/[^0-9]//g' temp2.txt)
if [ $some_var -eq 1 ]
then
echo "Ok"
else
echo "No file"
fi
rm -f temp.txt
rm -f temp2.txt
That's the script that answers the question "Is ABC.txt present in the directory?"
But you need to login in order to use this so : Follow the routine described in here http://www.linuxproblem.org/art_9.html in order to be able to SSH to given host without requiring a password and then add the following line at the top of the above script "ssh user#host".
Hope that helps..
P.S Using ssh is way easier and i think it's better than using ftp :)
I am using if statement to check for a condition and assign values. A mail will be sent after that. I executing the script ( bash ) but nothing really happens and I have to exit; could anyone tell me what I am doing wrong?
if [ $var -eq 0 ]
then
subject="there are zero issues"
else
subject="there are issues"
fi
mail -s "$subject" abc#gmail.com
The Unix mail command is waiting to receive a message body to send, but you have not provided one in your script. Try this:
$ mail -s "$subject" abc#gmail.com < /home/user/yourmessage.txt
where /home/user/yourmessage.txt contains some message you wish to include in the email.
I'm not sure why this code isn't working. Its not going to the copy command.
I successfully run this manually on the command line (without the check)
I don't think i'm performing a correct file check? Is there a better, cleaner way to write this?
I just want to make sure the file exists, if so, copy it over. Thanks.
#!/bin/bash
if [ $# != 1 ]; then
echo "Usage: getcnf.sh <remote-host>" 2>&1
exit 1
fi
#Declare variables
HOURDATE=`date '+%Y%m%d%H%M'`
STAMP=`date '+%Y%m%d-%H:%M'`
REMOTE_MYCNF=/var/log/mysoft/mysoft.log
BACKUP_DIR=/home/mysql/dev/logs/
export REMOTE_MYCNF HOURDATE STAMP
#Copy file over
echo "Checking for mysoft.log file $REMOTE_MYCNF $STAMP" 2>&1
if [ -f $REMOTE_MYCNF ]; then
echo "File exists lets bring a copy over...." 2>&1
/usr/bin/scp $1:$REMOTE_MYCNF $BACKUP_DIR$1.mysoft.log
echo "END CP" 2>&1
exit 0
else
echo "Unable to get file" 2>&1
exit 0
fi
your checking existing file on remote computer seems like:
you should do:
ssh $host "test -f $file"
if [ $? = 0 ]; then
use sh -x script.sh to see what is happening.
You are testing for the existence of a remote file
$1:$REMOTE_MYCNF
using the local name $REMOTE_MYCNF. The if test is never satisfied.
You don't check that $1 is set.
Your file check runs on the local machine - not on the remote.
Change your if to:
if[! -f $REMOTE_MYCNF -o ! -d $REMOTE_MYCNF];
I am currently creating an overnight job that calls a Unix script which in turn creates and transfers a file using ftp. I would like to check all possible return codes. The man page for ftp doesn't list return codes. Does anyone know where to find a list? Anyone with experience with this? We have other scripts that grep for certain return strings in the log, and they send an email when in error. However, they often miss unanticipated codes.
I am then putting the reason into the log and the email.
The ftp command does not return anything other than zero on most implementations that I've come across.
It's much better to process the three digit codes in the log - and if you're sending a binary file, you can check that bytes sent was correct.
The three digit codes are called 'series codes' and a list can be found here
I wrote a script to transfer only one file at a time and in that script use grep to check for the 226 Transfer complete message. If it finds it, grep returns 0.
ftp -niv < "$2"_ftp.tmp | grep "^226 "
Install the ncftp package. It comes with ncftpget and ncftpput which will each attempt to upload/download a single file, and return with a descriptive error code if there is a problem. See the “Diagnostics” section of the man page.
I think it is easier to run the ftp and check the exit code of ftp if something gone wrong.
I did this like the example below:
# ...
ftp -i -n $HOST 2>&1 1> $FTPLOG << EOF
quote USER $USER
quote PASS $PASSWD
cd $RFOLDER
binary
put $FOLDER/$FILE.sql.Z $FILE.sql.Z
bye
EOF
# Check the ftp util exit code (0 is ok, every else means an error occurred!)
EXITFTP=$?
if test $EXITFTP -ne 0; then echo "$D ERROR FTP" >> $LOG; exit 3; fi
if (grep "^Not connected." $FTPLOG); then echo "$D ERROR FTP CONNECT" >> $LOG; fi
if (grep "No such file" $FTPLOG); then echo "$D ERROR FTP NO SUCH FILE" >> $LOG; fi
if (grep "access denied" $FTPLOG ); then echo "$D ERROR FTP ACCESS DENIED" >> $LOG; fi
if (grep "^Please login" $FTPLOG ); then echo "$D ERROR FTP LOGIN" >> $LOG; fi
Edit: To catch errors I grep the output of the ftp command. But it's truly it's not the best solution.
I don't know how familier you are with a Scriptlanguage like Perl, Python or Ruby. They all have a FTP module which you can be used. This enables you to check for errors after each command. Here is a example in Perl:
#!/usr/bin/perl -w
use Net::FTP;
$ftp = Net::FTP->new("example.net") or die "Cannot connect to example.net: $#";
$ftp->login("username", "password") or die "Cannot login ", $ftp->message;
$ftp->cwd("/pub") or die "Cannot change working directory ", $ftp->message;
$ftp->binary;
$ftp->put("foo.bar") or die "Failed to upload ", $ftp->message;
$ftp->quit;
For this logic to work user need to redirect STDERR as well from ftp command as below
ftp -i -n $HOST >$FTPLOG 2>&1 << EOF
Below command will always assign 0 (success) as because ftp command wont return success or failure. So user should not depend on it
EXITFTP=$?
lame answer I know, but how about getting the ftp sources and see for yourself
I like the solution from Anurag, for the bytes transfered problem I have extended the command with grep -v "bytes"
ie
grep "^530" ftp_out2.txt | grep -v "byte"
-instead of 530 you can use all the error codes as Anurag did.
You said you wanted to FTP the file there, but you didn't say whether or not regular BSD FTP client was the only way you wanted to get it there. BSD FTP doesn't give you a return code for error conditions necessitating all that parsing, but there are a whole series of other Unix programs that can be used to transfer files by FTP if you or your administrator will install them. I will give you some examples of ways to transfer a file by FTP while still catching all error conditions with little amounts of code.
FTPUSER is your ftp user login name
FTPPASS is your ftp password
FILE is the local file you want to upload without any path info (eg file1.txt, not /whatever/file1.txt or whatever/file1.txt
FTPHOST is the remote machine you want to FTP to
REMOTEDIR is an ABSOLUTE PATH to the location on the remote machine you want to upload to
Here are the examples:
curl --user $FTPUSER:$FTPPASS -T $FILE ftp://$FTPHOST/%2f$REMOTEDIR
ftp-upload --host $FTPHOST --user $FTPUSER --password $FTPPASS --as $REMOTEDIR/$FILE $FILE
tnftp -u ftp://$FTPUSER:$FTPPASS#$FTPHOST/%2f$REMOTEDIR/$FILE $FILE
wput $FILE ftp://$FTPUSER:$FTPPASS#$FTPHOST/%2f$REMOTEDIR/$FILE
All of these programs will return a nonzero exit code if anything at all goes wrong, along with text that indicates what failed. You can test for this and then do whatever you want with the output, log it, email it, etc as you wished.
Please note the following however:
"%2f" is used in URLs to indicate that the following path is an absolute path on the remote machine. However, if your FTP server chroots you, you won't be able to bypass this.
for the commands above that use an actual URL (ftp://etc) to the server with the user and password embedded in it, the username and password MUST be URL-encoded if it contains special characters.
In some cases you can be flexible with the remote directory being absolute and local file being just the plain filename once you are familiar with the syntax of each program. You might just have to add a local directory environment variable or just hardcode everything.
IF you really, absolutely MUST use regular FTP client, one way you can test for failure is by, inside your script, including first a command that PUTs the file, followed by another that does a GET of the same file returning it under a different name. After FTP exits, simply test for the existence of the downloaded file in your shell script, or even checksum it against the original to make sure it transferred correctly. Yeah that stinks, but in my opinion it is better to have code that is easy to read than do tons of parsing for every possible error condition. BSD FTP is just not all that great.
Here is what I finally went with. Thanks for all the help. All the answers help lead me in the right direction.
It may be a little overkill, checking both the result and the log, but it should cover all of the bases.
echo "open ftp_ip
pwd
binary
lcd /out
cd /in
mput datafile.csv
quit"|ftp -iv > ftpreturn.log
ftpresult=$?
bytesindatafile=`wc -c datafile.csv | cut -d " " -f 1`
bytestransferred=`grep -e '^[0-9]* bytes sent' ftpreturn.log | cut -d " " -f 1`
ftptransfercomplete=`grep -e '226 ' ftpreturn.log | cut -d " " -f 1`
echo "-- FTP result code: $ftpresult" >> ftpreturn.log
echo "-- bytes in datafile: $bytesindatafile bytes" >> ftpreturn.log
echo "-- bytes transferred: $bytestransferred bytes sent" >> ftpreturn.log
if [ "$ftpresult" != "0" ] || [ "$bytestransferred" != "$bytesindatafile" ] || ["$ftptransfercomplete" != "226" ]
then
echo "-- *abend* FTP Error occurred" >> ftpreturn.log
mailx -s 'FTP error' `cat email.lst` < ftpreturn.log
else
echo "-- file sent via ftp successfully" >> ftpreturn.log
fi
Why not just store all output from the command to a log file, then check the return code from the command and, if it's not 0, send the log file in the email?