Shiny脚本执行shell命令失败,寻求在Shiny内的可行实现方法
It's totally common to hit snags running shell commands in Shiny even when they work perfectly in a regular R session—this almost always comes down to differences in environment context, permissions, or path resolution. Let’s walk through the key fixes for your calculate_maxent function:
1. Fix Working Directory & Path Reliability
Shiny apps run in a default working directory (usually your app’s root folder), and relying on setwd() is fragile. Instead, use absolute paths for all files and scripts to avoid confusion:
# Replace relative path with absolute path to your maxent directory maxent_dir <- "S:/Arbeitsgruppen VIRO/AG_Sch/Johannes Ptok_JoPt/Rpackages/rnaSEQ/data/maxent" # Use file.path() to build cross-platform-safe paths input_file <- file.path(maxent_dir, "Input_sequences") # Write sequences directly to the absolute path (no need for setwd()) cat(seq_vector, file = input_file, sep = "\n", append = TRUE) # Build command with absolute paths to the Perl scripts if(maxent_type == 3) { script_path <- file.path(maxent_dir, "score3.pl") } else if(maxent_type == 5) { script_path <- file.path(maxent_dir, "score5.pl") } cmd <- paste(script_path, input_file)
2. Explicitly Specify the Perl Interpreter Path
Shiny’s environment might not have Perl in its system PATH. To guarantee it finds the interpreter, use the full path to your Perl executable:
# Replace this with your actual Perl path (run `where perl` in Windows cmd to find it) perl_path <- "C:/Strawberry/perl/bin/perl.exe" # Update the command to call Perl directly cmd <- paste(perl_path, script_path, input_file)
3. Check Permissions
Shiny runs under a specific user account (like the server’s service account on Windows). Make sure this account has:
- Read access to the maxent directory and Perl scripts
- Write access to create/modify the
Input_sequencesfile in that directory
4. Capture Errors for Debugging
Right now, you’re only capturing standard output with shell(intern=TRUE), but error messages go to standard error. Switch to system2() to catch both, which makes debugging way easier:
# Replace shell() with system2() for better error handling result <- system2(perl_path, args = c(script_path, input_file), stdout = TRUE, stderr = TRUE) # Check if the command failed if(attr(result, "status") != 0) { stop("Maxent script failed: ", paste(result, collapse = "\n")) } # Process the output as before x <- result
5. Avoid Concurrent File Conflicts
If multiple users access your Shiny app at the same time, they’ll overwrite the same Input_sequences file. Use a temporary file instead to prevent this:
# Create a unique temp file (auto-cleaned up later) input_file <- tempfile(pattern = "maxent_input", tmpdir = maxent_dir, fileext = "") on.exit(unlink(input_file)) # Delete temp file when the function finishes # Write sequences to the temp file (no append needed—each call gets a fresh file) cat(seq_vector, file = input_file, sep = "\n")
Full Modified Function
Putting all these fixes together, here’s the updated version of your function:
calculate_maxent <- function(seq_vector, maxent_type){ maxent_dir <- "S:/Arbeitsgruppen VIRO/AG_Sch/Johannes Ptok_JoPt/Rpackages/rnaSEQ/data/maxent" perl_path <- "C:/Strawberry/perl/bin/perl.exe" # Update this to your Perl path! # Create unique temporary input file input_file <- tempfile(pattern = "maxent_input", tmpdir = maxent_dir, fileext = "") on.exit(unlink(input_file)) # Clean up temp file after execution # Write sequences to temp file cat(seq_vector, file = input_file, sep = "\n") # Select correct Perl script if(maxent_type == 3) { script_path <- file.path(maxent_dir, "score3.pl") } else if(maxent_type == 5) { script_path <- file.path(maxent_dir, "score5.pl") } else { stop("Invalid maxent_type: must be 3 or 5") } # Execute command with error capture result <- system2(perl_path, args = c(script_path, input_file), stdout = TRUE, stderr = TRUE) # Handle execution errors if(attr(result, "status") != 0) { stop("Failed to run maxent script: ", paste(result, collapse = "\n")) } # Extract and return scores x <- substr(result, regexpr("\t", result)[[1]] + 1, nchar(result)) return(x) }
Start with verifying the Perl path and permissions first—those are the most common causes of this issue. If you still get errors, the system2() error capture will show you exactly what’s breaking (like "file not found" or "permission denied").
内容的提问来源于stack exchange,提问作者Johannes Ptok

