Shell脚本自定义日志函数失效求助:标准输出/错误重定向问题
Let's break down why your current redirection isn't working and walk through the correct way to route stdout and stderr to your custom logging functions.
Why Your Original Syntax Fails
Your command block uses invalid shell redirection syntax:
{ ls -la; cd /tmp/kjhdakdha; ls -la } 2 | errorLog 1 | OutputLog
Here's what's wrong:
2 | errorLogdoesn't make sense to the shell. The|operator connects the stdout of one command to the stdin of another, but2is just a file descriptor number—you can't pipe a file descriptor directly like this.- You're mixing up file descriptor redirection (using
>/>&) with pipe syntax, which leads to the shell rejecting the command entirely.
Correct Solution: Use Process Substitution
To route stdout and stderr to separate custom functions, we'll use bash process substitution (>(command)), which creates a pseudo-file that feeds output to your function's stdin. This lets us handle each stream independently.
Step 1: Ensure Your Logging Functions Work with Stdin
First, make sure your OutputLog and errorLog functions read input from stdin (this is the standard way to handle piped input):
# Define log file paths OutputLogFile="/path/to/your/info.log" ErrorLogFile="/path/to/your/error.log" # Info logging function: reads lines from stdin, formats, and writes to log file OutputLog() { while IFS= read -r line; do # Add timestamp and log level echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $line" >> "$OutputLogFile" done } # Error logging function: same pattern for stderr errorLog() { while IFS= read -r line; do echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $line" >> "$ErrorLogFile" done }
IFS= read -r linepreserves leading/trailing spaces and backslashes in the input lines, which avoids mangling output likels -lalistings.
Step 2: Redirect Streams to Your Functions
Use process substitution to route stdout (fd 1) to OutputLog and stderr (fd 2) to errorLog:
{ ls -la; cd /tmp/kjhdakdha; ls -la; } 1> >(OutputLog) 2> >(errorLog)
Let's break this down:
1> >(OutputLog): Redirect stdout (file descriptor 1) to the pseudo-file created by>(OutputLog), which feeds all stdout lines into theOutputLogfunction's stdin.2> >(errorLog): Redirect stderr (file descriptor 2) toerrorLogthe same way.- The curly braces
{ ... }group your commands so their combined output/stderr is redirected.
Key Notes to Avoid Issues
- Use bash, not sh: Process substitution is a bash-specific feature. Make sure your script starts with
#!/bin/bash(not#!/bin/sh) to enable this. - Check file permissions: Ensure the user running the script has write access to
OutputLogFileandErrorLogFile. - Test edge cases: If your commands produce partial lines (e.g., progress bars), you might need to tweak the function to handle unbuffered input, but for standard line-based output like
lsor error messages, the above works perfectly.
Example Test Run
After setting up the functions and variables, run the command block. You'll see:
- The output of
ls -lainOutputLogFilewith timestamps and[INFO]tags. - The error message from
cd /tmp/kjhdakdha(since that directory doesn't exist) inErrorLogFilewith[ERROR]tags.
内容的提问来源于stack exchange,提问作者Suganya

