-
Notifications
You must be signed in to change notification settings - Fork 560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adjust ExtractResources.sh to be posix-compliant #492
adjust ExtractResources.sh to be posix-compliant #492
Conversation
fix pet state command close cmangos#492
Just ran into this issue a few minutes ago. Even using bash it still failed (probably because I didn't remove the #!/bin/sh :d). I replaced If this works for every system this script is supposed to run on, then I think it's a better solution than forcing the use of bash. ps: |
@Dwyriel Thanks for the suggestion, that's also the solution we came up with when discussing it on Discord recently, somebody™ just needs to commit it. We found a major memory leak in the mmap generator during that though, so got a bit sidetracked. 😅 And yes, For reference, here is the patch I came up with, combining Thorsten's changes and your suggestion for the exit code: diff --git a/contrib/extractor_scripts/ExtractResources.sh b/contrib/extractor_scripts/ExtractResources.sh
index dcc17997a1..a72f110d7b 100755
--- a/contrib/extractor_scripts/ExtractResources.sh
+++ b/contrib/extractor_scripts/ExtractResources.sh
@@ -144,8 +144,8 @@ then
echo "How many CPU threads should be used for extracting mmaps? (leave empty to use all available threads)"
read line
echo
- if [[ ! -z $line ]]; then
- if [[ $line =~ ^[1-9+]$ ]]; then
+ if [ ! -z $line ]; then
+ if [ "$(expr "$line" : "^[1-9][0-9]*$")" -gt 0 ]; then
NUM_THREAD=$line
else
echo "Only numbers are allowed!"
@@ -252,8 +252,8 @@ if [ "$USE_VMAPS" = "1" ]
then
echo "$(date): Start extraction of vmaps..." | tee -a $LOG_FILE
$PREFIX/vmap_extractor $VMAP_RES $VMAP_OPT_RES | tee -a $DETAIL_LOG_FILE
- exit_code="${PIPESTATUS[0]}"
- if [[ "$exit_code" -ne "0" ]]; then
+ exit_code="$?"
+ if [ "$exit_code" -ne "0" ]; then
echo "$(date): Extraction of vmaps failed with errors. Aborting extraction. See the log file for more details."
exit "$exit_code"
fi
@@ -264,8 +264,8 @@ then
fi
echo "$(date): Start assembling of vmaps..." | tee -a $LOG_FILE
$PREFIX/vmap_assembler ${OUTPUT_PATH:-.}/Buildings ${OUTPUT_PATH:-.}/vmaps | tee -a $DETAIL_LOG_FILE
- exit_code="${PIPESTATUS[0]}"
- if [[ "$exit_code" -ne "0" ]]; then
+ exit_code="$?"
+ if [ "$exit_code" -ne "0" ]; then
echo "$(date): Assembling of vmaps failed with errors. Aborting extraction. See the log file for more details."
exit "$exit_code"
fi |
Oh by the way, you can check if a script is compliant with the |
@Muehe hey neat, hope somebody™ commits it soon them :D Also, thanks for pointing out about shellcheck, didn't know about it. Ran the script through it and it had a few warnings mentioning the PIPESTATUS and a few other things as well, pretty useful. Cheers~ ^^ |
Merged as ca1526a Since this included some other changes I made a new commit, but put you as the author @Thorsten42 So this PR won't show as merged here on Github, but it is. Thanks for your input and sorry for the long wait. |
It's going to work, but it does the wrong thing. That $? gives the exit status of the last command, which in the case of a pipe is the exit status of the last command. So that would check the exit status of tee here, not the actual vmap_extractor/vmap_assembler command as originally intended. |
@evil-at-wow that is true yes... did a bit more digging trying to find a posix way to do so, and it seems there's a way that'd make it work. Simply setting pipefail ( That said, I'm not sure how exactly pipefail would interact with stdout and if tee would still execute or not, even if the piped program failed, so might not have the desired functionality. (I'm not very knowledgeable about posix or script stuff, sowwy >.<) |
Oh damn, thanks for pointing @evil-at-wow . However this same problem should occur with Seems this can be solved with moving the commands a bit and adding an eval though. |
Hmm, no that doesn't work quite right: $ echo $status
0
$ eval ` { ls /dontexists || echo status="$?"; } | tee test.txt`
ls: cannot access '/dontexists': No such file or directory
$ cat test.txt
status=2 Maybe |
@Muehe wrote a small cpp program that prints to stdout and returns 3 and did some testing with both eval and pipefail and those are the result: Eval prints "status=3" and writes both the stdout from the program plus the echo ("status=3") to the output file. Pipefail has the correct output both in the terminal and in the file, as it does not stop the piping, just doesn't overwrite $? if the return type of any piped program was not 0. script I used for testing: (eval one is the same as the linked but, changing ls to be my own program) set -o pipefail
/home/lotie/Downloads/a.out | tee ./stuff.txt
echo "$?" #output 3 revolutionary cpp program: std::cout << "some stuff" << std::endl;
return 3; Edit: if I print to std::cerr (stderr) tee does not pick it up, so yes ls is most likely writing to stderr, redirecting stderr to stdout would be a solution if you also want that output. |
@Dwyriel Since the stackexchange link you posted mentions that it might take up to a decade for this change to proliferate to all shells I installed $ set -o pipefail
dash: 2: set: Illegal option -o pipefail One alternative solution would be an output redirection:
The downside being that it would prevent the command outputs from being shown during the script execution. Another would be saving the exit code to a temporary file:
Or we could just completely remove the check as Thorsten initially suggested. |
@Muehe Well, found another solution that works well, but requires some cleanup after use, namely: named pipes mkfifo named_pipe
tee -a stuff.txt < named_pipe &
./a1.out > named_pipe 2>&1 #redirecting stderr is optional
echo $?
tee -a stuff.txt < named_pipe &
./a2.out > named_pipe 2>&1
echo $?
rm named_pipe #remove named pipe after use output:
file
Ran in every shell I tried (sh, bash, dash). I don't think removing the check is the best idea as there would be no feedback in case something went wrong, so the user might think the vmaps were extracted and assembled correctly when they weren't. Both saving the exit code to a temp file like you said and named pipes had the same result for me, so imo those are the best solutions so far. |
Interesting. I also found mktemp command in the meantime, which can be used to create temporary files with a randomised name. Also have to be manually deleted though, unless you want to rely on system settings. I'll play around with both approaches a bit, but intuitively the file approach seems to be a bit more readable IMHO, since it uses less output redirection. |
Ok so... while messing around with the actual script to see what works and what doesn't (and how well it works), I found another problem kind of related kind of not.. When I was getting to the vmap_extractor part, it seemed like it was just hanging, even when I used a non-modified script, and it indeed was. I ran it without piping it to tee and vmap_extractor would print a few things to the console then wait for user input to close itself. this is the output I was getting:
When piping to tee it'd just stay stuck at the I'm not very familiar with tee, but I don't think using tee with interactive programs is a good idea. I tried looking for a way to make it work and the only way I found was to run tee then pipe it into the program you want then pipe that into tee again, but it didn't work at all. So, putting that vmap_extractor (and possibly ad and vmap_assembler as well) may be interactive, either those programs need some reworking, or this script. Unless there's an actual way to do this properly and I'm just not aware. A possible workaround might be the use of script(1): script -c "command goes here" log_file.txt How it'd be incorporated in the script I'm not sure, might even require a second .sh that has the commands you wanna run, and it'd probably need some cleanup of the logfile as well as script writes some extra stuff at the beginning and end of the file. |
the output directory pollution should generally be noticed before vmaps extraction starts, so this is indeed a strange situation |
@Dwyriel This is because the program isn't running in it's own shell, so diff --git a/contrib/vmap_extractor/vmapextract/vmapexport.cpp b/contrib/vmap_extractor/vmapextract/vmapexport.cpp
index c265a59923..0d8272c627 100644
--- a/contrib/vmap_extractor/vmapextract/vmapexport.cpp
+++ b/contrib/vmap_extractor/vmapextract/vmapexport.cpp
@@ -478,6 +478,7 @@ int main(int argc, char** argv)
{
printf("Your output directory seems to be polluted, please use an empty directory!\n");
printf("<press return to exit>");
+ fflush(stdout);
char garbage[2];
scanf("%c", garbage);
return 1; Curiously this provides a test case for the conditions checking the exit code, the script indeed thinks it finished right now although it didn't. Also not sure where that mkdir line after originates from...
|
Oh hell, the line comes from here: if [ "$exit_code" -ne "0" ]; then
echo "$(date): Extraction of vmaps failed with errors. Aborting extraction. See the log file for more details."
exit "$exit_code"
fi
echo "$(date): Extracting of vmaps finished" | tee -a $LOG_FILE
if [ ! -d "$(pwd)/vmaps" ]
then
mkdir ${OUTPUT_PATH:-.}/vmaps
fi The problem is I started the script with parameters for input and output path, but the condition only checks if the directory exists in |
@Muehe unless this breaks some intended functionality in other platforms, wouldn't it be best if a program like vmap_extractor ran without any sort of interactions? Printing what went wrong and returning with a failure code would allow the script to take care of the rest. And also because the interaction output ("<press return to exit>") would be saved to the log file as well, which might be a bit unorthodox. ps: Now that I'm re-reading my last message I can see it might have sounded a bit rude or condescending. Sorry about that, it was really late and my brain was barely functional. |
Yes, very much so, and thus I'll probably just remove the
Don't worry, it didn't. Well to me at least. 😅 Small progress report, I tried both the
I think we were hitting that exception in 1. because we are using a Another thing I noticed is that log files are not overwritten/appended if they already exist, so will have to look into that as well. |
Found another inconsistency/problem with the most recent change:
if the user typed something containing whitespaces, the script will lay them out as multiple params rather than only one, meaning that if I typed
|
Yeah I actually went through all occurrences of SC2086 and changed them. It's pertinent because many of the variables are paths, which might contain spaces. Just need to do it for the other script as well before I push it. Ignored the occurrences of SC2162 ( |
@Dwyriel Pushed all the changes. Let me know if you find anything else. 👍 |
@Muehe well what do you know.. :d So, something quite weird is happening, two in fact, and I was not able to pinpoint what is causing it. This is the error I'm getting:
Was running the script from within the proper wow folder, I ran it both dry (no args) and with That said.. whatever the problem is might not be related to vmap_extractor at all.. ./vmap_extractor -l #no args
./vmap_extractor -l -d .//Data -o ./ext #args: ./ ./ext
./vmap_extractor -l -d .//Data -o ./ #args: ./ ./ so the command itself seems fine I think (maybe not the first one?), what isn't fine is that when I was passing an output dir, the previous parts of the script were still outputting to ./ and not to ./ext (clustering my wow folder). And of course, the second weird thing is how even when running it completely dry, or even by manually passing I did not have much time today to really look into it deeply, and tomorrow will be an even busier day for me, but I did try to check the paths it was passing to the prev commands as well and they seemed to be fine, so I really have no idea what is going wrong. Script is fresh from a recompilation I did earlier after pulling the latest changes, no modifications. Edit: If I tell the script I do not want high res maps or if I just pass the |
Figured it out, the problem is the overuse of quotes for some variables. Some of the variables prepare arguments for other commands, but because they're being used inside quotes they are passed as a singular argument to those programs rather than being laid out as they should. For example, this is how vmap_extractor was been run: ./vmap_extractor "-l" "-d .//Data -o ./" But the intended command would be: ./vmap_extractor "-l" "-d" ".//Data" "-o" "./" #the double / doesn't matter afaik Meaning the whitespaces are required to be there otherwise the program won't know how to interpret some of those arguments. This is a commit I made with the required changes for it to "run" eaa38a9, but there's still another problem that needs solving: If the client or output folder contain spaces, the commands won't execute as we'd encounter the same problem, so variables like Another issue I encountered is that the script does not check if ad failed or not, same goes for MoveMapGen, so it keeps executing when it most likely shouldn't. (pretty sure this was a problem even before removing Edit: A possible easy "solution" to the first problem would be making it less dynamic, requiring it to be run inside the client folder and outputting to a specific, hard coded, folder. I don't really consider this a solution, but it's a lot less work. Docs would also need some updating, so there's also that. |
Merged eaa38a9 thank you! ❤️ In my defence I did try running the script before pushing my fixes and it #worked-on-my-machine. 🙈 |
@Muehe Created a new PR #519 containing the fixes to the 2 other problems I mentioned, and a few extra things, though I did not add any checks to Do you think the script should check the exit code of |
@Dwyriel I'll try to get it merged tomorrow or over the weekend, but at a glance the changes look good. Not sure about |
@Muehe alrighty, I didn't want to touch MoveMapGen (yet) because it was actually giving me some trouble, but not really related to the script, but the system. Don't know why but after running for a while the system would freeze up and, after a few secs, kill the process. My guess is a memory leak somewhere. Either way I wanted to investigate the root cause to make sure what was going wrong before making any changes I wouldn't be able to test. |
Yeah, that's the memory leak I mentioned further up thread. Bit over my head though, I believe @cyberium and @insunaa have looked into this, but not sure if they made any progress yet. Extraction should still work with 32GB+swap/pagefile though. I only got 16GB+swap so I run into the same problem at the moment. |
@Muehe What a difference it made, total system mem usage never went above 2gb :D Made the changes and tested them, still haven't merged with the PR branch, have a look a it and let me know what you think db0f54e. If everything looks good I'll merge this commit into the PR branch. ps: speaking of PR branches, I realized the source branch of my previous PR (#518) was the master (where I made additional changes not related to this) and not the correct branch, so I closed it and opened a new one (#519). My bad there >.< |
The ExtractResources.sh script fails when used with sh since bash specific parts are used. (I closed my previous pull request to just use bash instead of sh since an sh compatible version would be preferred #491)
In this pull request the regex for checking the "number of threads for mmap" input is adjusted. Moreover, the previous version (
^[1-9+]$
) was also rejecting 10 cores:However, the parts using ${PIPESTATUS[0]} have been removed since other pipes are also not checked and sh compatible workarounds would definitely worsen the readability.
For me the script works like this with sh but I am not a shellscript guru. So please take a close look at it.