WIP: support command-line redirection of stdout/stderr
This commit is contained in:
parent
fe1e056196
commit
798a9dd9b1
@ -5,6 +5,7 @@ global/globals.C
|
||||
/* global/JobInfo/JobInfo.C in globals.C */
|
||||
global/argList/argList.C
|
||||
global/argList/argListHelp.C
|
||||
global/argList/argListRedirect.C
|
||||
global/clock/clock.C
|
||||
global/clockValue/clockValue.C
|
||||
global/cpuTime/cpuTimeCxx.C
|
||||
|
@ -27,6 +27,7 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "argListRedirect.H"
|
||||
#include "OSspecific.H"
|
||||
#include "Switch.H"
|
||||
#include "clock.H"
|
||||
@ -47,6 +48,7 @@ License
|
||||
#include "stringListOps.H"
|
||||
#include "fileOperation.H"
|
||||
#include "fileOperationInitialise.H"
|
||||
#include "fstreamPointer.H"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
@ -911,7 +913,9 @@ Foam::argList::argList
|
||||
runControl_(),
|
||||
args_(argc),
|
||||
options_(argc),
|
||||
libs_()
|
||||
libs_(),
|
||||
stdout_(nullptr),
|
||||
stderr_(nullptr)
|
||||
{
|
||||
// Pre-scan for some options needed for initial setup:
|
||||
// -fileHandler (takes an argument)
|
||||
@ -1018,6 +1022,53 @@ Foam::argList::argList
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Capture stdout/stderr redirection names. Filters argv
|
||||
Detail::redirectOutputs redirects(argc, argv);
|
||||
|
||||
// Perform output redirection
|
||||
if (redirects.active())
|
||||
{
|
||||
word suffix;
|
||||
|
||||
if (redirects.ranks_ && parRunControl_.parRun())
|
||||
{
|
||||
suffix = Foam::name(Pstream::myProcNo());
|
||||
}
|
||||
|
||||
if (!redirects.stdout_.empty())
|
||||
{
|
||||
fileName file(fileName::validate(redirects.stdout_));
|
||||
file.ext(suffix);
|
||||
|
||||
stdout_.reset(ofstreamPointer(file).release());
|
||||
}
|
||||
|
||||
if (!redirects.stderr_.empty())
|
||||
{
|
||||
fileName file(fileName::validate(redirects.stderr_));
|
||||
file.ext(suffix);
|
||||
|
||||
stderr_.reset(ofstreamPointer(file).release());
|
||||
}
|
||||
|
||||
if (stdout_)
|
||||
{
|
||||
Sout.attach(*stdout_);
|
||||
Pout.attach(*stdout_);
|
||||
}
|
||||
|
||||
if (stderr_)
|
||||
{
|
||||
Serr.attach(*stderr_);
|
||||
Perr.attach(*stderr_);
|
||||
}
|
||||
else if (redirects.join_)
|
||||
{
|
||||
Serr.attach(Sout.stdStream());
|
||||
Perr.attach(Sout.stdStream());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Convert argv -> args_ and capture ( ... ) lists
|
||||
regroupArgv(argc, argv);
|
||||
@ -1172,6 +1223,8 @@ Foam::argList::argList
|
||||
args_(args.args_),
|
||||
options_(options),
|
||||
libs_(),
|
||||
stdout_(nullptr),
|
||||
stderr_(nullptr),
|
||||
executable_(args.executable_),
|
||||
rootPath_(args.rootPath_),
|
||||
globalCase_(args.globalCase_),
|
||||
|
@ -146,6 +146,12 @@ class argList
|
||||
//- Additional libraries
|
||||
mutable dlLibraryTable libs_;
|
||||
|
||||
//- File redirection for stdout (Sout, Pout)
|
||||
std::unique_ptr<std::ostream> stdout_;
|
||||
|
||||
//- File redirection for stderr (Serr, Perr)
|
||||
std::unique_ptr<std::ostream> stderr_;
|
||||
|
||||
word executable_;
|
||||
fileName rootPath_;
|
||||
fileName globalCase_;
|
||||
|
@ -425,6 +425,16 @@ void Foam::argList::printUsage(bool full) const
|
||||
}
|
||||
|
||||
|
||||
// Redirections
|
||||
if (full)
|
||||
{
|
||||
printOption("stdout <file>", "Redirect stdout to file");
|
||||
printOption("stderr <file>", "Redirect stderr to file");
|
||||
printOption("join-stderr", "Join stderr to stdout");
|
||||
printOption("append-rank", "Append stdout/stderr files with MPI-rank");
|
||||
}
|
||||
|
||||
|
||||
// Place documentation/help options at the end
|
||||
|
||||
printOption("doc", "Display documentation in browser");
|
||||
|
175
src/OpenFOAM/global/argList/argListRedirect.C
Normal file
175
src/OpenFOAM/global/argList/argListRedirect.C
Normal file
@ -0,0 +1,175 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argListRedirect.H"
|
||||
#include "IOstreams.H"
|
||||
#include "boolList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline bool opt_join(const char* optName)
|
||||
{
|
||||
return strcmp(optName, "join-stderr") == 0;
|
||||
}
|
||||
|
||||
inline bool opt_rank(const char* optName)
|
||||
{
|
||||
return strcmp(optName, "append-rank") == 0;
|
||||
}
|
||||
|
||||
inline bool opt_stderr(const char* optName)
|
||||
{
|
||||
return strcmp(optName, "stderr") == 0;
|
||||
}
|
||||
|
||||
inline bool opt_stdout(const char* optName)
|
||||
{
|
||||
return strcmp(optName, "stdout") == 0;
|
||||
}
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::Detail::redirectOutputs::redirectOutputs(int& argc, char**& argv)
|
||||
:
|
||||
stdout_(),
|
||||
stderr_(),
|
||||
join_(false),
|
||||
ranks_(false)
|
||||
{
|
||||
List<bool> skip(label(argc), false);
|
||||
bool filter = false;
|
||||
|
||||
for (int argi = 1; argi < argc-1; ++argi)
|
||||
{
|
||||
if (argv[argi][0] == '-')
|
||||
{
|
||||
const char *optName = &argv[argi][1];
|
||||
|
||||
if (opt_join(optName))
|
||||
{
|
||||
join_ = true;
|
||||
filter = true;
|
||||
skip[argi] = true;
|
||||
}
|
||||
else if (opt_rank(optName))
|
||||
{
|
||||
ranks_ = true;
|
||||
filter = true;
|
||||
skip[argi] = true;
|
||||
}
|
||||
else if (opt_stdout(optName))
|
||||
{
|
||||
stdout_ = argv[argi+1];
|
||||
filter = true;
|
||||
skip[argi] = true;
|
||||
skip[argi+1] = true;
|
||||
++argi;
|
||||
}
|
||||
else if (opt_stderr(optName))
|
||||
{
|
||||
stderr_ = argv[argi+1];
|
||||
filter = true;
|
||||
skip[argi] = true;
|
||||
skip[argi+1] = true;
|
||||
++argi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Test final arg separately
|
||||
{
|
||||
const int argi = argc-1;
|
||||
|
||||
if (argi > 0 && argv[argi][0] == '-')
|
||||
{
|
||||
const char *optName = &argv[argi][1];
|
||||
|
||||
if (opt_join(optName))
|
||||
{
|
||||
join_ = true;
|
||||
filter = true;
|
||||
skip[argi] = true;
|
||||
}
|
||||
else if (opt_rank(optName))
|
||||
{
|
||||
ranks_ = true;
|
||||
filter = true;
|
||||
skip[argi] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (filter)
|
||||
{
|
||||
int nArgs = 1;
|
||||
|
||||
for (int argi = 1; argi < argc; ++argi)
|
||||
{
|
||||
if (!skip[argi])
|
||||
{
|
||||
argv[nArgs] = argv[argi];
|
||||
++nArgs;
|
||||
}
|
||||
}
|
||||
argc = nArgs;
|
||||
}
|
||||
|
||||
|
||||
// Resolve potential conflicts
|
||||
|
||||
if (!stderr_.empty())
|
||||
{
|
||||
if (stdout_.empty())
|
||||
{
|
||||
join_ = false;
|
||||
}
|
||||
else if (stdout_ == stderr_)
|
||||
{
|
||||
join_ = true;
|
||||
stderr_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::Detail::redirectOutputs::active() const
|
||||
{
|
||||
return join_ || !stdout_.empty() || !stderr_.empty();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
86
src/OpenFOAM/global/argList/argListRedirect.H
Normal file
86
src/OpenFOAM/global/argList/argListRedirect.H
Normal file
@ -0,0 +1,86 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::Detail::redirectOutputs
|
||||
|
||||
Description
|
||||
Helper class for redirecting outputs from within argList.
|
||||
Handles the following options:
|
||||
|
||||
\verbatim
|
||||
-stdout <file>
|
||||
-stderr <file>
|
||||
-join-stderr
|
||||
-append-rank
|
||||
\endverbatim
|
||||
|
||||
Note
|
||||
Not intended for general use
|
||||
|
||||
SourceFiles
|
||||
argListRedirect.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef argListRedirect_H
|
||||
#define argListRedirect_H
|
||||
|
||||
#include "string.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class redirectOutputs Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
struct redirectOutputs
|
||||
{
|
||||
string stdout_;
|
||||
string stderr_;
|
||||
bool join_;
|
||||
bool ranks_;
|
||||
|
||||
redirectOutputs(int& argc, char**& argv);
|
||||
|
||||
bool active() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Detail
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
Loading…
Reference in New Issue
Block a user