Write txt file in linux for .net Core (Docker) - linux

I am new in Linux and my API was created in .net core and running in Docker. The system i create will write/create a txt file that will input all errors logged in the API. My code to write is this
`public class WriteLogs
{
public void ErrorLogFile(string traceNo, string errorMsg)
{
DirectoryInfo dir = new DirectoryInfo(Startup.errorPath);
if (!dir.Exists)
{
dir.Create();
}
using (StreamWriter swLog = File.AppendText(Startup.errorPath + Startup.errorFileName + DateTime.Now.ToString("MMddyyyy") + ".txt"))
{
swLog.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") + " - Trace Number : " + traceNo + " " + errorMsg + "\n");
}
}
}`
the value in my startup is located in my appSettings.json file :
"ErrorPath": "C:\\BP\\",
"ErrorFileName": "BP-ParamLogs_",
This is working in windows environment but when i transfer my program to linux and change the ErrorPath to:
"ErrorPath": "/home/Logs/",
the file was not created.
My question is, do my syntax works in linux to write txt file or my path was wrong?

To answer your specific question about the syntax. \home\Logs\ should be /home/Logs/ as Linux uses forward-slash for path separator.
There's a chance that your program does not have write access to the /home/ directory. I've personally tried a similar program and I ran into System.UnauthorizedAccessException during the logs directory creation step.
Try running your program from the terminal with dotnet run to see the exception you might be getting. If you are also running into the System.UnauthorizedAccessException then run as root with sudo dotnet run

i just solved the problem by using command:
find . -name BP-Param*
from the first directory. After executing it. it was in the docker directory.

Related

How to do file inputs via node.js using emscripten?

I have a C++ project that I have converted into javascript using emscripten. I need help with implementing file input into the program via node. As I understand it the default file system in emscripten uses preloaded data that can only be done on a web page or web worker. I need mine to work with node.js on the command line.
Looking at the documentation I see that there's a way to use NODEFS instead of the default MEMFS which should allow me to do this. However, I'm unsure how I'm supposed to go about this. I don't really understand the test code that's provided.
Here's how the file handling is being done in the original C++ project:
void InputFile(std::string &fileName)
{
std::ifstream in(fileName);
if (in.fail())
{
std::cerr << "ERROR, Could not open " << fileName << std::endl;
exit(1);
}
}
But when I attempt to run the converted program with a file, node project.js -f test.file I get the error message: ERROR, Could not open test.file meaning that opening the file failed. The original C++ project was able to open the file without any issues, so I know there's not problem with the file itself.
I'm not sure what I have to do to make the converted project work with file inputs, any help would very much appreciated.
Explanation
WebAssembly module, built using emscripten, has no information about files in your physical file system. Instead, it uses a virtual file system. All you have to do is to create a link between files on your physical system to the files on the module's virtual system. NODEFS gives you this opportunity.
Quick solution
We will start at modifying your C++ code by adding the aforementioned link between physical and virtual file systems using embedded JS code (with EM_ASM). First (1), we create a directory '/temp' on the virtual file system where all referenced files will be located in. Then (2), we link this new virtual directory with a real physical location (the current working directory '.') where all the referenced files are already.
#include <emscripten.h>
#include <emscripten/bind.h>
#include <iostream>
#include <fstream>
void InputFile(const std::string &fileName)
{
EM_ASM(
FS.mkdir('/temp'); // (1)
FS.mount(NODEFS, {root : '.'}, '/temp');); // (2)
std::ifstream in(std::string("/temp/") + fileName);
if (in.fail())
{
std::cerr << "ERROR, Could not open " << fileName << std::endl;
exit(1);
}
}
EMSCRIPTEN_BINDINGS(Module)
{
emscripten::function("InputFile", &InputFile);
}
Now, because in the WebAssembly module, we are working with the virtual file systems, and not the physical one, each referenced file from the current directory (the root '.') is actually in the virtual directory previously linked ('/temp'). Hence, '/temp' directory precedes the name to the referenced file: std::ifstream in(std::string("/temp/") + fileName);.
Finally, we can compile this file. We force the synchronized compilation (to make sure the require loads the WASM module on time). Moreover, the option -s EXIT_RUNTIME=1 makes sure that the C++ command exit(1); finishes the execution. Also, we need to link Embind (--bind) and NODEFS (-lnodefs.js):
emcc project.cpp -o project.js -s WASM_ASYNC_COMPILATION=0 -s EXIT_RUNTIME=1 --bind -lnodefs.js
Testing
To test the WebAssembly module with the same calling convention as you have mentioned, we can use the following test.js script:
var Module = require('./project.js');
if (process.argv[3] && process.argv[2] === '-f') {
const filename = process.argv[3];
Module.InputFile(filename);
} else {
console.log('Pass the file with -f flag!');
}
To run the file, all you have to do is this: node test.js -f test.file
Comment
This approach works well if the referenced files are in the current working directory. In the case they are not, you could modify the code of the InputFile to extract the directory in which the fileName is, and then, mount the real-to-virtual directory accordingly.

Groovy: No such file exception but file is there ? Copying files on crossplateforms

I have an issue with Groovy\Jenkins when trying to copy files
The code I use is the following:
public void copy(String sources, String destination) {
Path source = Paths.get( join(this.script.WORKSPACE, sources) );
Path target = Paths.get( join(this.script.WORKSPACE, destination) );
Files.copy(source, target)
}
this.script.WORKSPACE is Jenkins workspace, and if this workspace is C:\Jenkins\Workspace\MyBranch and the sources are binaries\mybinary.dll then the join function will return:
C:\Jenkins\Workspace\MyBranch\mybinary.dll
At execution I receive the following error:
java.nio.file.NoSuchFileException: Y:\Jenkins\workspace\MyBranch\mybinary.dll
However the file is there, on the agent.
The thing is that I was using xcopy because I had to copy only on windows target (and it works without any issue, I isolated the change to the copy function, and now the windows copy is failling).
But now I have also to copy on redhat plateforms.
So I am looking for a crossplateform solution
Thank you !
So I found out this is a Jenkins related issue. Actually the pipeline is executed on the master, not the agent, so the file is looked for on the master, on which it does not exist.
I will have to use either sh scripts, or the jenkins stash function but it does not seem like I can have a cross plateform code here.

How to get NReco.PdfGenerator.LT working with Linux binaries?

I'm using NReco.PdfGenerator.LT to create a PDF document from a HTML page. This works fine on windows if I just point it at the wkhtmltopdf.exe executable, but this does not have the same effect on Linux.
HtmlToPdfConverter cvt = new HtmlToPdfConverter();
cvt.PdfToolPath = GetPdfToolPath();
// Windows: <current-dir>\wkhtmltopdf\win32\bin
// Linux: <current-dir>/wkhtmltopdf/linux/bin
cvt.WkHtmlToPdfExeName = GetPdfToolName();
// Windows: wkhtmltopdf.exe
// Linux: wkhtmltopdf
I just get this error:
Cannot generate PDF: Permission denied
Possible reasons of this error:
linux user who starts .net core program has no permissions to run "wkhtmltopdf". Also ensure that "wkhtmltopdf" file is marked as "executable" (x).
sometimes temp folder returned by Path.GetTempPath() is not accessible; another location for temp files may be specified with HtmlToPdfConverter.TempFilesPath property

AWS Lambda permission denied when trying to use ffmpeg

I want to write a handler that responds to S3 put events to convert any avi files that are uploaded to mp4. I doing it in Java, in Eclipse, with the AWS toolkit plugin. For video conversion, I am using ffmpeg with ffmpeg-cli-wrapper, and I have provided a static (linux) binary of ffmpeg in the source tree.
I have found that when I upload the function, the binary gets put in /var/task, but when I try to use the test function I've written, I get a "permission denied" error.
import net.bramp.ffmpeg.FFmpeg;
public class LambdaFunctionHandler implements RequestHandler<S3Event, String> {
private static final String FFMPEG = "/var/task/ffmpeg";
public String handleRequest(S3Event event, Context context) {
try {
FFmpeg ff = new FFmpeg(FFMPEG);
System.out.println(ff.version());
} catch (Exception e) {
e.printStackTrace();
}
return "foo";
}
}
And the first line of the stacktrace: java.io.IOException: Cannot run program "/var/task/ffmpeg": error=13, Permission denied.
How do I execute this binary? I have done as others have suggested and chmod 755 the binary before uploading, but it hasn't made a difference.
AWS Lambda runs on Amazon Linux. It is a known issue. Try building (with static enabled) and check if it works on Amazon Linux and upload that binary. You do not have the privileges to chmod the files in /var/task/. Or try this solution that works:
Move ffmpeg to /tmp
chmod 755 /tmp/ffmpeg
Call /tmp/ffmpeg
See this discussion for more info.
I ran into this issue recently, and after messing with various manual solutions, what really solved the issue was:
Create a Lambda Layer, with only the ffmpeg binary inside a bin/ folder
Create a Lambda Function to implement said layer, and in the python code run /opt/bin/ffmpeg
See https://aws.amazon.com/blogs/media/processing-user-generated-content-using-aws-lambda-and-ffmpeg/
As helloV mentioned, you might have to include a static ffmpeg binary and copy it to a location and execute from there.
A detailed answer, (node.js code) is given here

How do you get the path of the running script in groovy?

I'm writing a groovy script that I want to be controlled via a properties file stored in the same folder. However, I want to be able to call this script from anywhere. When I run the script it always looks for the properties file based on where it is run from, not where the script is.
How can I access the path of the script file from within the script?
You are correct that new File(".").getCanonicalPath() does not work. That returns the working directory.
To get the script directory
scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent
To get the script file path
scriptFile = getClass().protectionDomain.codeSource.location.path
As of Groovy 2.3.0 the #SourceURI annotation can be used to populate a variable with the URI of the script's location. This URI can then be used to get the path to the script:
import groovy.transform.SourceURI
import java.nio.file.Path
import java.nio.file.Paths
#SourceURI
URI sourceUri
Path scriptLocation = Paths.get(sourceUri)
Note that this will only work if the URI is a file: URI (or another URI scheme type with an installed FileSystemProvider), otherwise a FileSystemNotFoundException will be thrown by the Paths.get(URI) call. In particular, certain Groovy runtimes such as groovyshell and nextflow return a data: URI, which will not typically match an installed FileSystemProvider.
This makes sense if you are running the Groovy code as a script, otherwise the whole idea gets a little confusing, IMO. The workaround is here: https://issues.apache.org/jira/browse/GROOVY-1642
Basically this involves changing startGroovy.sh to pass in the location of the Groovy script as an environment variable.
As long as this information is not provided directly by Groovy, it's possible to modify the groovy.(sh|bat) starter script to make this property available as system property:
For unix boxes just change $GROOVY_HOME/bin/groovy (the sh script) to do
export JAVA_OPTS="$JAVA_OPTS -Dscript.name=$0"
before calling startGroovy
For Windows:
In startGroovy.bat add the following 2 lines right after the line with
the :init label (just before the parameter slurping starts):
#rem get name of script to launch with full path
set GROOVY_SCRIPT_NAME=%~f1
A bit further down in the batch file after the line that says "set
JAVA_OPTS=%JAVA_OPTS% -Dgroovy.starter.conf="%STARTER_CONF%" add the
line
set JAVA_OPTS=%JAVA_OPTS% -Dscript.name="%GROOVY_SCRIPT_NAME%"
For gradle user
I have same issue when I'm starting to work with gradle. I want to compile my thrift by remote thrift compiler (custom by my company).
Below is how I solved my issue:
task compileThrift {
doLast {
def projectLocation = projectDir.getAbsolutePath(); // HERE is what you've been looking for.
ssh.run {
session(remotes.compilerServer) {
// Delete existing thrift file.
cleanGeneratedFiles()
new File("$projectLocation/thrift/").eachFile() { f ->
def fileName=f.getName()
if(f.absolutePath.endsWith(".thrift")){
put from: f, into: "$compilerLocation/$fileName"
}
}
execute "mkdir -p $compilerLocation/gen-java"
def compileResult = execute "bash $compilerLocation/genjar $serviceName", logging: 'stdout', pty: true
assert compileResult.contains('SUCCESSFUL')
get from: "$compilerLocation/$serviceName" + '.jar', into: "$projectLocation/libs/"
}
}
}
}
One more solution. It works perfect even you run the script using GrovyConsole
File getScriptFile(){
new File(this.class.classLoader.getResourceLoader().loadGroovySource(this.class.name).toURI())
}
println getScriptFile()
workaround: for us it was running in an ANT environment and storing some location parent (knowing the subpath) in the Java environment properties (System.setProperty( "dirAncestor", "/foo" )) we could access the dir ancestor via Groovy's properties.get('dirAncestor').
maybe this will help for some scenarios mentioned here.

Resources