Asterisk tips fileexistance

As of Asterisk 1.4 the preferred method for determining if a file exists is using the STAT function: Asterisk func stat

Asterisk Tips and Tricks: Branching depending on the existance of one or more files on the local filesystem


IMPORTANT: This functionality is being deprecated in future versions of asterisk. Be sure to see the "global priority jumping option" on the Asterisk cmd System page for details on how to enable it in your environment if asterisk is not properly jumping to the right context.

Occasionally you need to build conditional logic into the dialplan to correctly handle errors such as trying to play back files that do not exist and so on. Asterisk has no built in command to test for files. The obvious soloution would seem to be to use a shell script to do the test, however some care is needed as Asterisk cannot read environment variables set during a call to Asterisk cmd System. The only available communications path from the shell is the value of exit() called when the program in the shell exits - which suits us fine as we only need a binary value. Using the shell has the added advantage of handling name globbing and so on.

So, create an executable script call, perhaps, fileexists:


  1. !/bin/bash
  2. Test for the existance of files based on shell globbing patterns

for a in $1;
do
if [ -f $a ] ; then
  1. there are one or more files that match;
exit;
else
  1. there aren't any files that match;
exit 1;
fi;
done;


Then call it from the dialplan using a statement such as:


...
exten => s,3,System(/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/${EXTEN}.gsm) ; test for the existance of this path as a recording
exten => s,4,NoOp(Phew! The file exists...)
exten => s,104,NoOp(Panic! There was no such file!)
...


Upon return the System() call will step to either n+1 if the script exits =0 or n+101 if it exits >0.

For a practical example see the high density IVR code at Asterisk tips IVR menu.

Note: it should be possible to encode the script directly in the parameter to System() however I've been unable to build exactly the right structure of escaping required for /bin/sh... If you can get it to work please add the construct to this page. (:biggrin:)

When I couldn't find where Asterisk wanted to execute System() shell scripts, I found this works:
even simpler since 'test' is built into the shell:
exten => s,3,System(test -e /var/lib/asterisk/sounds/transit-ivr/${EXTEN}.gsm)
exten => ... (the rest is the same!)

The above code will now return the channel variable SYSTEMSTATUS

FAILURE Could not execute the specified command
SUCCESS Specified command successfully executed

But we note that on testing :-
-- Executing [531@international:1] NoOp("SIP/2206-b2dbbab8", "This is a system call to test for a file") in new stack
    -- Executing [531@international:2] System("SIP/2206-b2dbbab8", "test -e /var/lib/asterisk/sounds/*54322.gsm") in new stack
    -- Executing [531@international:3] NoOp("SIP/2206-b2dbbab8", "SUCCESS") in new stack
    -- Executing [531@international:4] System("SIP/2206-b2dbbab8", "test -e /var/lib/asterisk/sounds/notafile.gsm") in new stack
    -- Executing [531@international:5] NoOp("SIP/2206-b2dbbab8", "APPERROR") in new stack
    -- Executing [531@international:6] Hangup("SIP/2206-b2dbbab8", "") in new stack


So the safest check is to check the SYSTEMSTATUS varible is = SUCCESS and fail on anything else.

for exmple

exten => _531XXXXX,1,Noop(This is a system call to test for a file)
exten => _531XXXXX,n,System(test -e /var/lib/asterisk/sounds/*${EXTEN:3}.gsm)
exten => _531XXXXX,n,Noop(${SYSTEMSTATUS})
exten => _531XXXXX,n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?yes:no)
exten => _531XXXXX,n(no),Noop( FILE NOT PRESENT ${SYSTEMSTATUS})
exten => _531XXXXX,n,Hangup()
exten => _531XXXXX,n(yes),Noop( FILE PRESENT ${SYSTEMSTATUS})
exten => _531XXXXX,n,Hangup()


See also


As of Asterisk 1.4 the preferred method for determining if a file exists is using the STAT function: Asterisk func stat

Asterisk Tips and Tricks: Branching depending on the existance of one or more files on the local filesystem


IMPORTANT: This functionality is being deprecated in future versions of asterisk. Be sure to see the "global priority jumping option" on the Asterisk cmd System page for details on how to enable it in your environment if asterisk is not properly jumping to the right context.

Occasionally you need to build conditional logic into the dialplan to correctly handle errors such as trying to play back files that do not exist and so on. Asterisk has no built in command to test for files. The obvious soloution would seem to be to use a shell script to do the test, however some care is needed as Asterisk cannot read environment variables set during a call to Asterisk cmd System. The only available communications path from the shell is the value of exit() called when the program in the shell exits - which suits us fine as we only need a binary value. Using the shell has the added advantage of handling name globbing and so on.

So, create an executable script call, perhaps, fileexists:


  1. !/bin/bash
  2. Test for the existance of files based on shell globbing patterns

for a in $1;
do
if [ -f $a ] ; then
  1. there are one or more files that match;
exit;
else
  1. there aren't any files that match;
exit 1;
fi;
done;


Then call it from the dialplan using a statement such as:


...
exten => s,3,System(/var/lib/asterisk/sounds/transit-ivr/filexists /var/lib/asterisk/sounds/transit-ivr/${EXTEN}.gsm) ; test for the existance of this path as a recording
exten => s,4,NoOp(Phew! The file exists...)
exten => s,104,NoOp(Panic! There was no such file!)
...


Upon return the System() call will step to either n+1 if the script exits =0 or n+101 if it exits >0.

For a practical example see the high density IVR code at Asterisk tips IVR menu.

Note: it should be possible to encode the script directly in the parameter to System() however I've been unable to build exactly the right structure of escaping required for /bin/sh... If you can get it to work please add the construct to this page. (:biggrin:)

When I couldn't find where Asterisk wanted to execute System() shell scripts, I found this works:
even simpler since 'test' is built into the shell:
exten => s,3,System(test -e /var/lib/asterisk/sounds/transit-ivr/${EXTEN}.gsm)
exten => ... (the rest is the same!)

The above code will now return the channel variable SYSTEMSTATUS

FAILURE Could not execute the specified command
SUCCESS Specified command successfully executed

But we note that on testing :-
-- Executing [531@international:1] NoOp("SIP/2206-b2dbbab8", "This is a system call to test for a file") in new stack
    -- Executing [531@international:2] System("SIP/2206-b2dbbab8", "test -e /var/lib/asterisk/sounds/*54322.gsm") in new stack
    -- Executing [531@international:3] NoOp("SIP/2206-b2dbbab8", "SUCCESS") in new stack
    -- Executing [531@international:4] System("SIP/2206-b2dbbab8", "test -e /var/lib/asterisk/sounds/notafile.gsm") in new stack
    -- Executing [531@international:5] NoOp("SIP/2206-b2dbbab8", "APPERROR") in new stack
    -- Executing [531@international:6] Hangup("SIP/2206-b2dbbab8", "") in new stack


So the safest check is to check the SYSTEMSTATUS varible is = SUCCESS and fail on anything else.

for exmple

exten => _531XXXXX,1,Noop(This is a system call to test for a file)
exten => _531XXXXX,n,System(test -e /var/lib/asterisk/sounds/*${EXTEN:3}.gsm)
exten => _531XXXXX,n,Noop(${SYSTEMSTATUS})
exten => _531XXXXX,n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?yes:no)
exten => _531XXXXX,n(no),Noop( FILE NOT PRESENT ${SYSTEMSTATUS})
exten => _531XXXXX,n,Hangup()
exten => _531XXXXX,n(yes),Noop( FILE PRESENT ${SYSTEMSTATUS})
exten => _531XXXXX,n,Hangup()


See also


Created by: kb1_kanobe, Last modification: Fri 01 of Jun, 2012 (05:54 UTC) by admin
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+