CFEXECUTE permission denied after minor point upgrade

Stack:
Ubuntu 22.04 LTS
Java (JDK) 20.0.2
Tomcat 9.0.83
Lucee 6.1.0.243
Apache 2.4.52
MySQL 8.0.41

Thank you to the Lucee team BTW for their continued work on Lucee and CF. I’m an older dev with some legacy code that I’ve been able to maintain quite easily with Lucee.

However, I noticed a problem today and it’s embarrassing because it involves a back up process that I didn’t check on and it hasn’t been running.

I use this line to kick off a shell script to back up some databases.

<cfexecute name="bash" arguments="/opt/mysqlbackups.sh #databaseName#" timeout="2400" variable="standardOut" errorVariable="returnedError"></cfexecute>

alternately, I could also use:

<cfscript>
cfexecute( name="bash" arguments="/opt/mysqlbackups.sh #databaseName#", variable="standardOut" , errorVariable="returnedError" , timeout="2400");
</cfscript>

Either way will (or did) work. Been simple and error free for years.

On October 27, 2024, I updated Lucee from 6.x to 6.1.x and that is also the last date that the MySQL backups which this particular script calls worked. No backup files were created after that date. And the relevant updated Lucee directory files are also dated October 27.

After that, the code no longer works, and I get this erorr:

java.io.IOException: Cannot run program "bash": error=13, Permission denied

Even when I simply try to call bash and not a script, I get the same problem (specifying path to bash in this example):

<cfexecute name="/usr/bin/bash" arguments="which bash" timeout="2400" variable="standardOut" errorVariable="returnedError"></cfexecute>

Results in:

java.io.IOException: Cannot run program "/usr/bin/bash": error=13, Permission denied

Today I have checked everything I can think of to solve this.

  • file permissions and ownership on shell script - correct (tomcat:tomcat) and 0750 plus the .sh file is executable
  • directory permissions and ownership for target files - correct
  • test the shell script from the command line - yes and works perfectly

This feels like deja vu from a time long ago, but I cannot figure out what is causing Lucee to think it no longer has permission to hand this off to bash.

After checking another shell script that CFEXECUTE uses (related to Imagemagick), same problem. CFEXECUTE will not run these shell scripts anymore. Permissions for bash and for the scripts are correct.

oh that sucks, strange indeed.

a couple of ideas to try

  • use the newish directory argument for cfexecute
  • call the bash script directly
  • can you read / write the shell script or (a copy! ) via fileRead / fileWrite?

What user is lucee running under? did you try running those scripts as that same user?

Nothing jumps out in JIRA that we’ve changed in that period and I’ve also just reviewed the files for changes in that period?

https://luceeserver.atlassian.net/issues/?jql=labels%20%3D%20"cfexecute"

Thank you!

The docs show that the directory argument was introduced in 5.3.8.1 and this was working well past that version. That said, would it be best to use the current directory of the site running Lucee? The script is in /opt which of course is not the directory of the particular instance of Lucee nor the site where this CFEXECUTE is called from.

Yes, I can call the script directly and pass in an argument (database name) which is what ColdFusion does for me.

Have not tried fileRead or fileWrite. I will look into that.

regarding directory, from memory, back in the old days, before the directory argument, on windows, cfexecute used to default to c:\windows\system32, which wasn’t great, maybe try /opt ? (not sure if this will help TBH)

nothing has changed in the unit tests for cfexecute in long time

do the any of these curl examples work for you?

Created “test.cfc” in same directory and pasted your code

Lucee 6.1.0.243 Error (expression)
Message	invalid component definition, can't find component [testbox.system.compat.framework.TestCase]

I am going back through and verifying permissions and mods on all Lucee files…

Also updated to latest Lucee and still getting error. I’ve checked, rechecked and checked again the shell script permissions as well as Lucee / CF. And hte script can be called from the command line as well, so it is executable.

Lucee 6.2.0.321 Error (application)
Message	Error invoking external process
Detail	java.io.IOException: Cannot run program "bash": error=13, Permission denied

I’ve updated to Java 24 (Open JDK 24). No change. Full Lucee error:

Lucee 6.2.0.321 Error (application)
Message	Error invoking external process
Detail	java.io.IOException: Cannot run program "bash": error=13, Permission denied
AI (Experimental)	For AI-driven exception analysis setup, see AI Setup Guide.
Stacktrace	The Error Occurred in
path/to/my/file/file.cfm: line 21
Java Stacktrace	lucee.runtime.exp.ApplicationException: Error invoking external process
 at lucee.runtime.tag.Execute.doEndTag(Execute.java:265)
 at -REDACTED FILE LOCATION - 
 at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:1093)
 at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:987)
 at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:63)
 at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:42)
 at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2785)
 at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2772)
 at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2743)
 at lucee.runtime.engine.Request.exe(Request.java:45)
 at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1099)
 at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1056)
 at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
 at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
 at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:670)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
 at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:424)
 at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
 at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)
 at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
 at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
 at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.base/java.lang.Thread.run(Thread.java:1447)
Timestamp	3/23/25 10:48:20 PM EDT

PROGRESS!

I down graded back to OpenJDK 20.0.2, at which point the bash script would run when called through CFEXECUTE. However, new error which I have never had before.

Also, kind of frustrating that I have to regress. Perhaps once I solve this mysqldump problem I can try OpenJDK24 again.

Permission denied mysqldump: mysqldump: Got errno 0 on write

Just to clarify why this is a CF issue:, or I think it is: I can call the script from the command line and it works as it should, backing up the database and writing the file. When I call the script from Lucee/CF, it will now execute through CFEXECUTE (after down grading to Java 20), but mysqldump throws an error as shown above.

So, it’s not a folder/file permission issue because when the shell script is called directly, it has no problem writing the output to the destination. Only when called through CFEXECUTE do I get an error shown above.

Java 23 and 24 would not proceed with the CFEXECUTE tag, but Java 20 does.

Java 24 still isn’t all working with Lucee, there are some outstanding issues, only 23 passes all unit tests, they did some more date handling changes again (sigh).

I actually saw something similar but different when putting together the installer test suite, at one point Lucee was picking up the github runner JVM, which was 17, I think I remember seeing something like this, once I started using the bundled 21 JVM, the error was resolved

But I can’t quite remember

this is coming from a .sh file yeah?

can you echo out whoami in the line before?

Permission denied mysqldump: mysqldump: Got errno 0 on write

What kind of sorcery is this?

So… what if I said that everything is working as of this morning?

But to your question, when I add WHOAMI / $USER in this block:

if [ $? -eq 0 ]; then
  echo "$USER Backup of ${DATABASE_NAME} completed successfully. - "
else
  echo "$USER Error found during backup ${DATABASE_NAME} - "
fi

It returns “tomcat” which is the correct user calling the script. And tomcat is owner and group of destination directory for the backup files.

As I wrote at the start of this reply, I get up this morning, run the code again - the CF page which calls this .sh script via CFEXECUTE and… it’s working.

This makes NO SENSE. I’ve never had any kind of code act like this - not working and now working with no changes. When I swapped out the Java versions from 24 back to 20, I not only restarted Tomcat, I restarted the machine itself as I usually do in when upgrading or down grading so that I can be 100% sure everything comes back to life. And the shell script was still returning the error:

Permission denied mysqldump: mysqldump: Got errno 0 on write

Here is the entire code for both the CFEXECUTE and the shell script.

<!--- set default messages --->
<cfparam name="standardOutString" default ="" />
<cfparam name="returnedErrorString" default ="" />

<!--- loop through --->
<cfloop query="getDBList">
		
	<!--- via tag call --->
	<cfexecute name="bash" arguments="/opt/bash-mysqlbackup-cf.sh #databaseName#" timeout="240" variable="standardOut" errorVariable="returnedError"></cfexecute>
	
	
	<!--- via cfscript
	<cfscript>
	cfexecute( name="bash" arguments="/opt/mysqlbackups-cf.sh #databaseName#", variable="standardOut", errorVariable="returnedError", timeout="240");
	</cfscript>
	--->
	
	<cfset standardOutString=listAppend(standardOutString,"<br />#standardOut#") />
	<cfset returnedErrorString=listAppend(returnedErrorString,"<br />#returnedError#") />
	
</cfloop>


<!--- send mail --->
<cfmail useTLS="true" from=#fromEmail#" to="#toEmail#" subject="Task: #numberFormat(url.thisTask, '00')#: Databases backed up" type="html">
Standard out: <br />
#standardOutString#
<br /><br />
Error: <br />
#returnedErrorString#
<br /><br />
</cfmail>

And the shell script called via CFEXECUTE in each loop iteration:

#!/bin/bash
 
################################################################
##
##   MySQL Database Backup Script 
##   Written By: Rahul Kumar
##   URL: https://tecadmin.net/bash-script-mysql-database-backup/
##   Last Update: Jan 05, 2019
##
################################################################
 
export PATH=/bin:/usr/bin:/usr/local/bin
TODAY=`date +"20%y%m%d-%H%M%S"`


# Pass in the DB name from the command line 
# as a single name or multiple, space separated 
# $1 for one db, or $1 $2 $3 etc for multiple
# 
echo "$1: "


 
################################################################
################## Update below values  ########################
 
DB_BACKUP_PATH='/path/to/my/backups/daily/'$1
MYSQL_HOST='127.0.0.1'
MYSQL_PORT='3306'
MYSQL_USER='*****'
MYSQL_PASSWORD='***********'
DATABASE_NAME=$1
BACKUP_RETAIN_DAYS=60   ## Number of days to keep local backup copy
 
#################################################################
 
#mkdir -p ${DB_BACKUP_PATH}/${TODAY}
echo "Backup started for ${DATABASE_NAME}. - "


mysqldump -h ${MYSQL_HOST} \
   -P ${MYSQL_PORT} \
   -u ${MYSQL_USER} \
   -p${MYSQL_PASSWORD} \
   ${DATABASE_NAME} | gzip > ${DB_BACKUP_PATH}/${DATABASE_NAME}-${TODAY}.sql.gz
   

if [ $? -eq 0 ]; then
  echo "Backup of ${DATABASE_NAME} completed successfully. - "
else
  echo "Error found during backup ${DATABASE_NAME} - "
fi
 

##### Remove backups older than {BACKUP_RETAIN_DAYS} days  #####
 
DBDELDATE=`date +"20%y%m%d-%H%M%S" --date="${BACKUP_RETAIN_DAYS} days ago"`

if [ ! -z ${DB_BACKUP_PATH} ]; then
      cd ${DB_BACKUP_PATH}
      if [ ! -z ${DBDELDATE} ] && [ -d ${DBDELDATE} ]; then
            rm -rf ${DBDELDATE}
      fi
fi
 
### End of script ####