在码头启动或创建其工作目录之前无法删除码头工作目录

Unable to delete jetty working directory before jetty starts or creates it's working directory

我有点 运行 这个有趣的问题。我想在 jetty 下次重新启动之前删除 jetty 工作目录。该应用程序有 2 war 个文件,这是使用嵌入码头实现的。工作文件夹的名称如下所示:

jetty-0_0_0_0-10000-oaxui_war-_ui_oax-any-4214704288653178451

jetty-0_0_0_0-10000-oaxservice_war-_api_oax-any-1938823993160354573

选项 1:我们有 run.sh 实际启动的文件 JettyServer.So 我想在此之前将以下代码放入文件中。

echo "now deleting"
DELTEMP="rm -rf /tmp/jetty*"
exec $DELTEMP
echo "deleted....."


Result: It actually deletes the jetty working directory but does not let it create one working directory also.

选项 2:在我们提供的位置创建一个临时目录,如下所示,然后使用 run.sh 及以上命令删除此文件夹,但路径将是自定义的。不幸的是,这也没有帮助,因为首先没有创建工作目录。

private HandlerCollection getWebAppHandlers() throws SQLException, NamingException{
        //Setting the war and context path for the service layer: oaxservice
        File tempDir1 = new File("/faw/service/appshell/tempdir/");
        File tempDir2 = new File("/faw/service/appshell/tempdir/");
        WebAppContext serviceWebapp = new WebAppContext();
        tempDir1.mkdirs();
        serviceWebapp.setTempDirectory(tempDir1);
        serviceWebapp.setWar(APPSHELL_API_WAR_FILE_PATH);
        serviceWebapp.setContextPath(APPSHELL_API_CONTEXT_PATH);


        //setting the war and context path for the UI layer: oaxui
        WebAppContext uiWebapp = new WebAppContext();
        tempDir2.mkdirs();
        uiWebapp.setTempDirectory(tempDir2);
        uiWebapp.setWar(APPSHELL_UI_WAR_FILE_PATH);
        uiWebapp.setContextPath(APPSHELL_UI_CONTEXT_PATH);
        uiWebapp.setAllowNullPathInfo(true);
        uiWebapp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");

        //set error page handler for the UI context
        uiWebapp.setErrorHandler(new CustomErrorHandler());

        //handling the multiple war files using HandlerCollection.
        HandlerCollection handlerCollection = new HandlerCollection();
        handlerCollection.setHandlers(new Handler[]{serviceWebapp, uiWebapp});
        return handlerCollection;
    }

下面是完整的 JettyServer.java 文件

public class JettyServer {

    private final static Logger logger = Logger.getLogger(JettyServer.class.getName());
    private static final int JETTY_PORT = 10000;
    private static final String JETTY_REALM_PROPERTIES_FILE_NAME = "realm.properties";
    private static final String JETTY_REALM_NAME = "myrealm";

    private static final String APPSHELL_WAR_FOLDER  = "/faw/service/appshell/target/";
    private static final String APPSHELL_UI_WAR_FILE_PATH = APPSHELL_WAR_FOLDER+"oaxui.war";
    private static final String APPSHELL_API_WAR_FILE_PATH = APPSHELL_WAR_FOLDER+"oaxservice.war";
    private static final String APPSHELL_API_CONTEXT_PATH  = "/api/oax";
    private static final String APPSHELL_UI_CONTEXT_PATH  = "/ui/oax";

    private static final String JETTY_CONFIG_FOLDER = "/faw/service/appshell/config/";
    private static final String JETTY_CONFIG_FILE = JETTY_CONFIG_FOLDER+"datasource.properties";
    private static final String JETTY_CONFIG_DATASOURCE_URL = "datasource.url";
    private static final String JETTY_CONFIG_APPSHELL_SCHEMA_NAME = "appshell.datasource.username";
    private static final String JETTY_CONFIG_APPSHELL_SCHEMA_PWD = "appshell.datasource.password";
    private static final String JETTY_CONFIG_APPSHELL_DS_INITIAL_POOL_SIZE = "appshell.datasource.initialPoolSize";
    private static final String JETTY_CONFIG_APPSHELL_DS_MAX_POOL_SIZE = "appshell.datasource.maxPoolSize";

    private static final String JETTY_CONFIG_FAWCOMMON_SCHEMA_NAME = "fawcommon.datasource.username";
    private static final String JETTY_CONFIG_FAWCOMMON_SCHEMA_PWD = "fawcommon.datasource.password";
    private static final String JETTY_CONFIG_FAWCOMMON_DS_INITIAL_POOL_SIZE = "fawcommon.datasource.initialPoolSize";
    private static final String JETTY_CONFIG_FAWCOMMON_DS_MAX_POOL_SIZE = "fawcommon.datasource.maxPoolSize";

    private static final int INITIAL_POOL_SIZE_DEFAULT = 0;
    private static final int MAX_POOL_SIZE_DEFAULT = 50;

    private static final String JNDI_NAME_FAWAPPSHELL = "jdbc/CXOMetadataDatasource";
    private static final String JNDI_NAME_FAWCOMMON = "jdbc/FawCommonDatasource";

    private static final String JETTY_REQUEST_LOG_FILE_NAME = "/faw/logs/appshell/applogs/jetty-request.yyyy_mm_dd.log";
    private static final String JETTY_REQUEST_LOG_FILE_NAME_DATE_FORMAT = "yyyy_MM_dd";
    private static final boolean JETTY_REQUEST_LOG_FILE_APPEND = true;
    private static final int JETTY_REQUEST_LOG_FILE_RETAIN_DAYS = 31;
    private static final String JETTY_STDOUT_LOG_FILE_NAME = "/faw/logs/appshell/applogs/jetty-out.yyyy_mm_dd.log";

    private static final int MAX_REQUEST_HEADER_SIZE = 65535;

    private static final String SSL_SERVER_KEY_STROKE_PATH="/faw/tmp/customscript/certs/server.jks";
    private static final String SSL_TRUST_KEY_STROKE_PATH="/faw/tmp/customscript/certs/trust.jks";
    private static final String SSL_KEY_STROKE_KEY="changeit";

    public static QueuedThreadPool threadPool;

    public JettyServer() {

        try {


            //Redirect system out and system error to our print stream.
            RolloverFileOutputStream os = new RolloverFileOutputStream(JETTY_STDOUT_LOG_FILE_NAME, true);
            PrintStream logStream = new PrintStream(os);
            System.setOut(logStream);
            System.setErr(logStream);

            Server server = new Server(JETTY_PORT);
            server.addBean(getLoginService());
            //Set SSL context
            if (isIDCSEnvironment) {
                try {
                    logger.info("Configuring Jetty SSL..");
                    HttpConfiguration http_config = new HttpConfiguration();
                    http_config.setSecureScheme("https");
                    http_config.setSecurePort(JETTY_PORT);
                    SslContextFactory sslContextFactory = new SslContextFactory.Server();
                    sslContextFactory.setKeyStorePath(SSL_SERVER_KEY_STROKE_PATH);
                    sslContextFactory.setCertAlias("server");
                    sslContextFactory.setKeyStorePassword(SSL_KEY_STROKE_KEY);
                    sslContextFactory.setTrustStorePath(SSL_TRUST_KEY_STROKE_PATH);
                    sslContextFactory.setTrustStorePassword(SSL_KEY_STROKE_KEY);
                    HttpConfiguration https_config = new HttpConfiguration(http_config);
                    https_config.addCustomizer(new SecureRequestCustomizer());
                    ServerConnector https = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(https_config));
                    https.setPort(JETTY_PORT);
                    server.setConnectors(new Connector[]{https});
                    logger.info("Jetty SSL successfully configured..");
                } catch (Exception e){
                    logger.severe("Error configuring Jetty SSL.."+e);
                    throw e;
                }
            }
            Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
            classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
                    "org.eclipse.jetty.plus.webapp.EnvConfiguration",
                    "org.eclipse.jetty.plus.webapp.PlusConfiguration");

            //register oaxui and oaxservice web apps
            HandlerCollection webAppHandlers = getWebAppHandlers();

            for (Connector c : server.getConnectors()) {
                c.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setRequestHeaderSize(MAX_REQUEST_HEADER_SIZE);
                c.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setSendServerVersion(false);
            }

            threadPool = (QueuedThreadPool) server.getThreadPool();

            // request logs
            RequestLogHandler requestLogHandler = new RequestLogHandler();
            AsyncRequestLogWriter asyncRequestLogWriter = new AsyncRequestLogWriter(JETTY_REQUEST_LOG_FILE_NAME);
            asyncRequestLogWriter.setFilenameDateFormat(JETTY_REQUEST_LOG_FILE_NAME_DATE_FORMAT);
            asyncRequestLogWriter.setAppend(JETTY_REQUEST_LOG_FILE_APPEND);
            asyncRequestLogWriter.setRetainDays(JETTY_REQUEST_LOG_FILE_RETAIN_DAYS);
            asyncRequestLogWriter.setTimeZone(TimeZone.getDefault().getID());
            requestLogHandler.setRequestLog(new AppShellCustomRequestLog(asyncRequestLogWriter));
            webAppHandlers.addHandler(requestLogHandler);

            StatisticsHandler statisticsHandler = new StatisticsHandler();
            statisticsHandler.setHandler(new AppshellStatisticsHandler());
            webAppHandlers.addHandler(statisticsHandler);

            // set handler
            server.setHandler(webAppHandlers);

            //start jettyMetricsPsr
            JettyMetricStatistics.logJettyMetrics();

            // set error handler
            server.addBean(new CustomErrorHandler());

            // GZip Handler
            GzipHandler gzip = new GzipHandler();
            server.setHandler(gzip);
            gzip.setHandler(webAppHandlers);


            //setting server attribute for datasources
            server.setAttribute("fawappshellDS", new Resource(JNDI_NAME_FAWAPPSHELL, DatasourceUtil.getFawAppshellDatasource()));
            server.setAttribute("fawcommonDS", new Resource(JNDI_NAME_FAWCOMMON, DatasourceUtil.getCommonDatasource()));
            //new Resource(server, JNDI_NAME_FAWAPPSHELL, getFawAppshellDatasource());
            //new Resource(server, JNDI_NAME_FAWCOMMON, getFawCommonDatasource());

            Map<String, String> configDetails;
            if (isIDCSEnvironment) {
                configDetails = DatasourceUtil.getConfigMap();
            } else {
                configDetails = DatasourceUtil.configMapInternal;
            }
            if (isIDCSEnvironment && configDetails.containsKey(PODDB_ATP_ENABLED) && BooleanUtils.toBoolean(configDetails.get(PODDB_ATP_ENABLED))){
                configDetails.put(DatabagProperties.LCM_MASTER_PROPERTY,"true");
                try {
                    DBUtils.migrateDBATP(configDetails, DatasourceUtil.getFawAppshellDatasourceATP());
                    configDetails.remove(DatabagProperties.LCM_MASTER_PROPERTY, "true");
                } catch(SQLException e){
                    logger.info("Exception while executing DBUtils.migrateDBATP.");
                    if(LCMUtils.isATPDBDown(e)) {
                        logger.info("Redis flow starts....Skipping consumption from Redis for now");
                    }
                    else{
                        logger.info("This is not eligible for redis flow. Actual Exception : "+ e);
                        throw e;
                    }
                }
            } else if (isIDCSEnvironment && configDetails.containsKey(PODDB_ATP_ENABLED) && !BooleanUtils.toBoolean(configDetails.get(PODDB_ATP_ENABLED))){
                try{
                    DBUtils.migrateDB();
                } catch (FawLCMPluginException e) {
                    logger.info(" This is not eligible for Redis consumption and exception is : " + e);
                }
            }

            //For Dev env..
            if (!isIDCSEnvironment && configDetails.containsKey(PODDB_ATP_ENABLED) && BooleanUtils.toBoolean(configDetails.get(PODDB_ATP_ENABLED))){
                configDetails.put(DatabagProperties.LCM_MASTER_PROPERTY,"true");
                try{
                    DBUtils.migrateDBATP(configDetails,DatasourceUtil.getDevFawAppshellDatasourceATP());
                    configDetails.remove(DatabagProperties.LCM_MASTER_PROPERTY,"true");
                }
                catch(SQLException e){
                    logger.info("Exception while executing DBUtils.migrateDBATP for dev environment.");
                    if(LCMUtils.isATPDBDown(e)) {
                        logger.info("Redis flow starts....Skipping consumption from Redis for now");
                    } else{
                        logger.info("This is not eligible for redis flow. Actual Exception for dev: "+ e);
                    }
                }
            } else if (!isIDCSEnvironment && configDetails.containsKey(PODDB_ATP_ENABLED) && !BooleanUtils.toBoolean(configDetails.get(PODDB_ATP_ENABLED))){
                try {
                    DBUtils.migrateDB();
                }catch (FawLCMPluginException e) {
                    logger.info(" This is not eligible for Redis consumption and exception in dev is : " + e);
                }
            }
            server.start();
            server.join();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private HandlerCollection getWebAppHandlers() throws SQLException, NamingException{
        //Setting the war and context path for the service layer: oaxservice
        File tempDir1 = new File("/faw/service/appshell/tempdir/");
        File tempDir2 = new File("/faw/service/appshell/tempdir/");
        WebAppContext serviceWebapp = new WebAppContext();
        tempDir1.mkdirs();
        serviceWebapp.setTempDirectory(tempDir1);
        serviceWebapp.setWar(APPSHELL_API_WAR_FILE_PATH);
        serviceWebapp.setContextPath(APPSHELL_API_CONTEXT_PATH);


        //setting the war and context path for the UI layer: oaxui
        WebAppContext uiWebapp = new WebAppContext();
        tempDir2.mkdirs();
        uiWebapp.setTempDirectory(tempDir2);
        uiWebapp.setWar(APPSHELL_UI_WAR_FILE_PATH);
        uiWebapp.setContextPath(APPSHELL_UI_CONTEXT_PATH);
        uiWebapp.setAllowNullPathInfo(true);
        uiWebapp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");

        //set error page handler for the UI context
        uiWebapp.setErrorHandler(new CustomErrorHandler());

        //handling the multiple war files using HandlerCollection.
        HandlerCollection handlerCollection = new HandlerCollection();
        handlerCollection.setHandlers(new Handler[]{serviceWebapp, uiWebapp});
        return handlerCollection;
    }

    /**
     * The name of the LoginService needs to correspond to what is configured a webapp's web.xml which is
     * <realm-name>myrealm</realm-name> and since it has a lifecycle of its own, we register it as a bean
     * with the Jetty server object so it can be started and stopped according to the lifecycle of the server itself.
     *
     * @return the login service instance
     * @throws FileNotFoundException In case realmProps is null
     */
    public LoginService getLoginService() throws IOException {
        URL realmProps = JettyServer.class.getClassLoader().getResource(JETTY_REALM_PROPERTIES_FILE_NAME);

        if (realmProps == null)
            throw new FileNotFoundException("Unable to find " + JETTY_REALM_PROPERTIES_FILE_NAME);
        return new HashLoginService(JETTY_REALM_NAME, realmProps.toExternalForm());
    }

    public static void main(String[] args) {
        new JettyServer();
    }
}

Run.sh 文件:

#!/bin/bash
set -eu  # Exit on error
set -o pipefail  # Fail a pipe if any sub-command fails.
VERSION=1.0

cd "$(dirname "[=13=]")"
RED='3[0;31m'
ORANGE='3[0;33m'
GREEN='3[0;32m'
NC='3[0m' # No Color

function die() {
  printf "${RED}%s\n${NC}" "" >&2
  exit 1
}

function warn() {
  printf "${ORANGE}%s\n${NC}" ""
}

function info() {
  printf "${GREEN}%s\n${NC}" ""
}

CURR_PID=$$

mem_args=8192
info "mem args "$mem_args

export MAX_MEM=$mem_args
    #put the managed server specific variable setting below, then export the variables

    USER_MEM_ARGS="-Xms4096m -Xmx"$MAX_MEM"m -XX:MetaspaceSize=1024M -XX:MaxMetaspaceSize=1024m"
    export USER_MEM_ARGS
    info "USER_MEM_ARGS= ${USER_MEM_ARGS}"

#FAW_JAVA_OPTIONS="-Djava.util.logging.config.file=/faw/service/appshell/config/ucp_log.properties -Doracle.jdbc.fanEnabled=false $USER_MEM_ARGS -Xloggc:/faw/logs/appshell/applogs/gc.jetty.log -XX:+HeapDumpOnOutOfMemoryError -XshowSettings:vm -XX:+PrintCodeCache -XX:ReservedCodeCacheSize=512M -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=maxage=30m,defaultrecording=true,stackdepth=1024,dumponexit=true,dumponexitpath=/faw/logs/jetty/jetty_1618996595.jfr -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+ExitOnOutOfMemoryError -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=4 -XX:GCLogFileSize=5M -XX:HeapDumpPath=/faw/logs/appshell_hprof-dumps_`date +%x_%r|awk -F" " '{print }'|sed  's/\//_/g'`.hprof"
FAW_JAVA_OPTIONS="-Djava.util.logging.config.file=/faw/service/appshell/config/ucp_log.properties -Doracle.jdbc.fanEnabled=false $USER_MEM_ARGS -Xloggc:/faw/logs/appshell/applogs/gc.jetty.log -XX:+HeapDumpOnOutOfMemoryError -XshowSettings:vm -XX:+PrintCodeCache -XX:ReservedCodeCacheSize=512M -XX:+UnlockCommercialFeatures -XX:+FlightRecorder  -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+ExitOnOutOfMemoryError -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=4 -XX:GCLogFileSize=5M -XX:HeapDumpPath=/faw/logs/appshell_hprof-dumps_`date +%x_%r|awk -F" " '{print }'|sed  's/\//_/g'`.hprof"

echo "now deleting"
DELTEMP="rm -rf /tmp/jetty*"
exec $DELTEMP
echo "deleted....."

info "FAW_JAVA_OPTIONS= ${FAW_JAVA_OPTIONS}"
if [[  -e "/faw/environment" ]]; then
sh /faw/tmp/customscript/setUpTLSCerts.sh
fi
CMD="java ${FAW_JAVA_OPTIONS} -cp /faw/service/appshell/target:/faw/service/appshell/libs/* oracle.biapps.cxo.docker.jetty.server.JettyServer --lib /faw/service/appshell/libs"
ulimit -c 0
# Now execute it
info "Executing: $CMD"
exec $CMD

感谢任何帮助。谢谢。

感谢“Joakim Erdfelt”的输入。知道了。以下解决方案在嵌入式码头中对我来说效果很好。我将创建一个自定义删除方法,用于先删除目录,然后创建码头工作目录。

public void cleanJettyWorkingDirectory(){
    final File folder = new File(JETTY_TEMP_WORKING_DIRECTORY);
    final File[] files = folder.listFiles((dir, name) -> name.matches( "oax.*" ));

    if (files!=null && files.length > 0) {
        for ( final File file : files ) {
            try {
                FileUtils.deleteDirectory(file);
                logger.info("Cleaning of the directory is completed.");
            } catch (IOException e) {
                logger.info("Unable to delete the Jetty working directory");
            }
        }
    }else{
        logger.info("No working directory file is present starting with oax for deletion.");
    }
}

此外,在设置 war 时,我们将执行以下操作来创建目录:

       try {
            cleanJettyWorkingDirectory();
            logger.info("starting to create temp working directory for oax service ");
            java.nio.file.Path oaxServicePath = Files.createTempDirectory("oaxservice");
            String oaxServiceTempPath = oaxServicePath.toString();

            logger.info("starting to create temp working directory for oax ui ");
            java.nio.file.Path uiPath = Files.createTempDirectory("oaxui");
            String oaxUIServiceTempPath = uiPath.toString();

            File oaxServiceTempDir = new File(oaxServiceTempPath);
            File oaxUITempDir = new File(oaxUIServiceTempPath);
            serviceWebapp.setTempDirectory(oaxServiceTempDir);
            uiWebapp.setTempDirectory(oaxUITempDir);
            logger.info("The process of creating working directory is completed.");
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Exception while creating directories.",e);
        }