echo with pipe in sh script creates filename with "?" - echo

I'm confronted with a rather strange problem an echo command causes in a script.
It's supposed to be really REALLY basic stuff, but still, there's something "off".
Suppose, I have this script:
#!/bin/bash
# SERVERPID='cat lite_server_pid.txt'
# kill -9 $SERVERPID
nohup java -Xmx3G -Xms2G -jar tekkit_lite_065.jar nogui > output.txt &
echo $! > lite_server_pid.txt
Yes, this starts my own little Minecraft/Tekkit-Server. ;-)
The Problem is, the file thats created is (for some reason) named
lite_server_pid.txt?
and YES, this includes the "?"! Doing the same command in shell, a file without ? is correctly created! Also, the content of the file is the desired processID.
Still, the ? following the filename is a major problem...
What am I doing wrong?

Check your file for DOS line endings. I suspect that ? is actually your terminal's attempt to display a carriage return (\r). Since bash expects UNIX-style newlines, the carriage return part of the DOS newline (\r\n) is treated as a legal character for the file name.
Run your script through dos2unix.

Related

Perl SYSTEM command fails with "Bad file descriptor" when running via Jenkins

I have a simple system command to copy file from one folder to another:
my $cmd = "xcopy /Y c:\DBs\Support\db.bak c:\jenkins\workdir\sql-bak-files";
When I try to run the following system commands, all fails:
1. my $res = qx/$cmd/;
2. my $res = qx($cmd);
3. using back ticks
All tries returned the error: Error number -1, error message: "Bad file descriptor".
When trying to use system($cmd) the error was Error number 65280, error message: "No such file or directory".
This perl code is running via Jenkins (ver 2.190.1) and perl v5.26.0.
This problem started after migrating the code from mercurial to git, but I don't think it's related.
It worked before, but now always fail :(
A backslash has a special meaning in a Perl quoted string. It is used to escape the following character - to "turn off" any special meaning. If you want to use a backslash in a Perl quoted string, then you need to use another backslash to escape it.
my $cmd = 'xcopy /Y c:\\DBs\\Support\\db.bak c:\\jenkins\\workdir\\sql-bak-files';
Alternatively, Perl recognises forward slashes in Windows paths, so it might be easier to replace your code with this:
my $cmd = 'xcopy /Y c:/DBs/Support/db.bak c:/jenkins/workdir/sql-bak-files';
Note that in both cases I have replaced your double-quotes with single-quotes. This has no effect on your problem, but it seems strange to use double-quoted strings if you're not using any of their special characteristics (like the expansion of variables).
Update: To debug a problem like this, you can try printing the string.
$ perl -E'say "xcopy /Y c:\DBs\Support\db.bak c:\jenkins\workdir\sql-bak-files"'
xcopy /Y c:DBsSupportdb.bak c:jenkinsworkdirsql-bak-files

sed command is not working properly

I'm trying to replace the word in shell script with sed -e command but its not replacing , please help on that, i have tried the below
we have separate file in /data/docs/config.log, in that file there is a word ?account for example ,
username acc, passsword acc, ?account.name
this ?account word needs to be replaced with word 'GLOBAL' using sed -e command ,
reacc = GLOBAL
sed -e "s/?account/$reacc/g" /data/docs/config.log > /data/docs/newconfig.log
but here the file newconfig.log has created with 0 size , no output written to the file , its not replacing its an empty file,
the output should be username acc, passsword acc, GLOBAL.name in newconfig.log
Being the only person who can reproduce the problem, you are pretty much on your own. There are plenty of things you can do to analyze the problem, though.
Double-check the shell. Don't have blind faith in #!/bin/sh. In cygwin for example, /bin/sh is an alias for bash. Verify with: echo $SHELL
Check permissions and file system. Do you have rights to write to the output file? Is the disk full? Does cat /data/docs/config.log > /data/docs/newconfig.log work? Test again in a different folder.
Double-check the output file. Is it really empty, or is the file system just slow with updating the file size? Is sed really finished? Test without output redirection; see if the output is dumped to stdout.
Test with a small file; one or two lines is enough.
If even that does not work, then test sed itself. Who knows, maybe you have a weird alias that hides the real sed. The most trivial filter is sed -e '', which should simply echo every line you type (just like cat without parameters). Does that work? Then try some simple patterns.
Systematically iterate between test cases that succeed and test case that fail, until you have found the breaking point. Doing so, you should be able to find the cause. Sorry, that's all I can do for you right now.
Remove spaces around =. Try after making
reacc=GLOBAL

How to empty a file in fish?

In bash shell scripting, I would typically run :> file to empty a file.
Now using fish, things are slightly different and the above command doesn't work.
What is fish equivalent?
Although it's not as short as :, true is a command that will work everywhere and produces no output:
true > file
Probably the easiest way that will be work in both Fish and Bash is to do echo "" > file
EDIT: Commenter was absolutely right echo "" > file produces a file with a newline, the correct command I was thinking of to create an empty file is cat /dev/null > file.
There is, and always was the magic method called touch which set change time to actual or create non-existent file. For compatiblity I suggest you to use this way in all scripts that you write (even if you write bash code).

CMD: Export all the screen content to a text file

In command prompt - How do I export all the content of the screen to a text file(basically a copy command, just not by using right-clicking and the clipboard)
This command works, but only for the commands you executed, not the actual output as well
doskey /HISTORY > history.txt
If you want to append a file instead of constantly making a new one/deleting the old one's content, use double > marks. A single > mark will overwrite all the file's content.
Overwrite file
MyCommand.exe>file.txt
^This will open file.txt if it already exists and overwrite the data, or create a new file and fill it with your output
Append file from its end-point
MyCommand.exe>>file.txt
^This will append file.txt from its current end of file if it already exists, or create a new file and fill it with your output.
Update #1 (advanced):
My batch-fu has improved over time, so here's some minor updates.
If you want to differentiate between error output and normal output for a program that correctly uses Standard streams, STDOUT/STDERR, you can do this with minor changes to the syntax. I'll just use > for overwriting for these examples, but they work perfectly fine with >> for append, in regards to file-piping output re-direction.
The 1 before the >> or > is the flag for STDOUT. If you need to actually output the number one or two before the re-direction symbols, this can lead to strange, unintuitive errors if you don't know about this mechanism. That's especially relevant when outputting a single result number into a file. 2 before the re-direction symbols is for STDERR.
Now that you know that you have more than one stream available, this is a good time to show the benefits of outputting to nul. Now, outputting to nul works the same way conceptually as outputting to a file. You don't see the content in your console. Instead of it going to file or your console output, it goes into the void.
STDERR to file and suppress STDOUT
MyCommand.exe 1>nul 2>errors.txt
STDERR to file to only log errors. Will keep STDOUT in console
MyCommand.exe 2>errors.txt
STDOUT to file and suppress STDERR
MyCommand.exe 1>file.txt 2>nul
STDOUT only to file. Will keep STDERR in console
MyCommand.exe 1>file.txt
STDOUT to one file and STDERR to another file
MyCommand.exe 1>stdout.txt 2>errors.txt
The only caveat I have here is that it can create a 0-byte file for an unused stream if one of the streams never gets used. Basically, if no errors occurred, you might end up with a 0-byte errors.txt file.
Update #2
I started noticing weird behavior when writing console apps that wrote directly to STDERR, and realized that if I wanted my error output to go to the same file when using basic piping, I either had to combine streams 1 and 2 or just use STDOUT. The problem with that problem is I didn't know about the correct way to combine streams, which is this:
%command% > outputfile 2>&1
Therefore, if you want all STDOUT and STDERR piped into the same stream, make sure to use that like so:
MyCommand.exe > file.txt 2>&1
The redirector actually defaults to 1> or 1>>, even if you don't explicitly use 1 in front of it if you don't use a number in front of it, and the 2>&1 combines the streams.
Update #3 (simple)
Null for Everything
If you want to completely suppress STDOUT and STDERR you can do it this way. As a warning not all text pipes use STDOUT and STDERR but it will work for a vast majority of use cases.
STD* to null
MyCommand.exe>nul 2>&1
Copying a CMD or Powershell session's command output
If all you want is the command output from a CMD or Powershell session that you just finished up, or any other shell for that matter you can usually just select that console from that session, CTRL + A to select all content, then CTRL + C to copy the content. Then you can do whatever you like with the copied content while it's in your clipboard.
Just see this page
in cmd type:
Command | clip
Then open a *.Txt file and Paste. That's it. Done.
If you are looking for each command separately
To export all the output of the command prompt in text files. Simply follow the following syntax.
C:> [syntax] >file.txt
The above command will create result of syntax in file.txt. Where new file.txt will be created on the current folder that you are in.
For example,
C:Result> dir >file.txt
To copy the whole session, Try this:
Copy & Paste a command session as follows:
1.) At the end of your session, click the upper left corner to display the menu.
Then select.. Edit -> Select all
2.) Again, click the upper left corner to display the menu.
Then select.. Edit -> Copy
3.) Open your favorite text editor and use Ctrl+V or your normal
Paste operation to paste in the text.
If your batch file is not interactive and you don't need to see it run then this should work.
#echo off
call file.bat >textfile.txt 2>&1
Otherwise use a tee filter. There are many, some not NT compatible. SFK the Swiss Army Knife has a tee feature and is still being developed. Maybe that will work for you.
How about this:
<command> > <filename.txt> & <filename.txt>
Example:
ipconfig /all > network.txt & network.txt
This will give the results in Notepad instead of the command prompt.
From command prompt Run as Administrator. Example below is to print a list of Services running on your PC run the command below:
net start > c:\netstart.txt
You should see a copy of the text file you just exported with a listing all the PC services running at the root of your C:\ drive.
If you want to output ALL verbosity, not just stdout. But also any printf statements made by the program, any warnings, infos, etc, you have to add 2>&1 at the end of the command line.
In your case, the command will be
Program.exe > file.txt 2>&1

Running a perl script in a batch file

i have a perl script that is used in updating my awstats logs of my website. The script works fine if i just paste it in cmd (Windows) but the moment i paste it in a batch file, it messes up the format of the files generated (they should be prepended with current date/time). The code is:
perl C:\PROGRA~2\AWStats\tools\awstats_buildstaticpages.pl -config=mywebsite -update -awstatsprog=C:\PROGRA~2\AWStats\wwwroot\cgi-bin\awstats.pl -dir=C:\myfolder\stats\reports -builddate=%YYYY%MM -buildpdf=C:\PROGRA~2\HTMLDOC\ghtmldoc.exe -staticlinksext=asp`
The resulting files generated is mysite.201008.asp if i paste it in cmd and execute BUT In a batch file with the same script, my resulting file is mysite.MM.asp.
Any idea why this is happening?
The problem is caused by %YYYY%MM.
"%" is a special symbol in batch files. You need to escape it by doubling it: %%YYYY%%MM.
It appears you have to escape the '%' characters.
The command shell doing variable substitution on %YYYY% which I'm guessing is not defined in your environment, so it substitutes the empty string for that "variable".
Unfortunately, there are no opaque quotes in the Windows shell.