Now that it’s possible to run NServiceBus on Linux, have you? If so, we’d love to hear from you!
We’d love to find out:
Did it work for you as expected?
What’s the scope of the project you used to test?
Did you run into any problems? (If so we’d like to fix them.)
What can we do to make it easier and better?
And of course we’d like to find out some tech specs from you, like:
What Linux distribution/version are you using?
What message transport and persistence are you using?
We’re really confident in this release, but want to get more feedback from those of you trying out the actual bits before we go to RC. Sound off in this thread, or if you don’t feel comfortable sharing your details, send us an email at support@particular.net with the subject “NServiceBus Linux Feedback”.
I’m aware that this is a very old post/question. But I figured it sounds like the right place to post all these years later.
We’re currently in the process of changing our developer machines to Linux (Mint Cinnamon in my case) for those of us who want to get rid of Windows from their dev boxes.
Migrating to running our systems on Linux will be a later step as this is even more involved. My thoughts will only concern running a dev environment and developing on a Linux machine.
Did it work for you as expected?
Most of the challenges we were (are) facing are not related to NServiceBus, but more general things like:
some code was/still is OS-dependent (but is not relevant for a dev machine)
PowerShell scripts that don’t behave identical on Windows and Linux
What’s the scope of the project you used to test?
For now it’s one big part of our platform. Everything we need to run the entire system on a developer machine is made ready for Linux. The second part will follow once we’re up and running completely on Linux dev machines.
Did you run into any problems? (If so we’d like to fix them.)
NServiceBus related things we didn’t notcie anything on the runtime side yet. The one thing that doesn’t work as expected involves auto-generated Persistence Scripts. As suggested in Controlling script generation • Sql Persistence • Particular Docs we commit the generated scripts to our repositories. The problem that we have is, that the line breaks always show up as changed after building on Linux. I’ll provide the details at the end of this post.
What can we do to make it easier and better?
So far above issue is the only one we faced.
What Linux distribution/version are you using?
Linux Mint 22.3 with Cinnamon
What message transport and persistence are you using?
SQL Server Transport and MS SQL Persistence
Back to the problem with the generated scripts. All the scripts show up in git as changed on Linux (it’s fine on windows)
The scripts that get regenerated on every build have a mix of line endings as git ls-files --eol | grep “.sql” shows i/lf w/mixed but i/lf w/lf would be my expectation to not see uncommitted changes in git. I would expect the generated scripts to respect the OS line endings and not having a seemingly random mix of LF and CRLF.
I’ve visualized line endings using cat -vET with one of the generated sql files to verify the problem.
We’re starting to use .gitattributes in the repo root to avoid problems between Windows and Linux machines and not having to rely on local autocrlf settings.
Are you aware of this issue that seems to be just ignored completely (or irrelevant) in Windows?
Our .gitattributes is * text=auto already, with nothing else.
The problem though is not how the files appear after a clean checkout or inside the repo. They show as i/lf w/lf as I expected. When I run a build the Saga and Outbox .sql files are regenerated and then have a mixed line endings which in turn show up as all the .sql files have changed.
Our configuration for the script generation is as follows.
And as suggested in the article referenced above, we commit these .sql scripts to our repository.
If these show up as changed in git on every build you can imagine how it’s impossible to work on a linux dev machine.
I have prepared a gist with “after clean checkout” and “after build” versions of one of the generated files with visualized line endings using cat -vET.
A $ at the end of the line means it’s a LF and the ^M represents a CR → ^M$ is a CRLF. You can see that the generated files have mixed line endings and cause uncommitted changes after every build.
I hope I managed to explain what the issue is. Let me know.
If you look for example at MsSqlServerSagaScriptWriter.WriteTableNameVariable() you’ll see that there are line breaks in the code (L.23) which will lead to whatever is the linebreak on the building OS with applied .gitattributes rules, e.g. CRLF if you build the published nuget packages under Windows (what you do based on the effective line breaks), it would be LF if you built the published packages under Linux. Where as the line break that is caused by writer.WriteLine( will be according to the running OS using Environment.NewLine under the hood. There’s also L.113 where there is an explicit \r\n which then causes a CRLF no matter on which OS you build the published nuget packages.
All this inevitably causes a chaos in line breaks, unless the published nuget packages are built on Windows and the developers (us) use it only on Windows. Any other constellation will cause the behavior I described in the previous message.
e.g. if you at some point decided to build the nuget packages on Linux all Windows developers using that feature would see the behavior we see now on Linux
Hey @philippdolder, when you change your .gitattributes file, that doesn’t change the entire history of the repo automatically, so you can have exactly that problem. You have to renormalize the line endings in your repo after changing .gitattributes so that the line endings are stored correctly. Once you do that, when you check out the code on Linux it will land on your machine with LF line endings, and if you check it out on Windows it will land on that machine with CRLF.
The second issue is that you are bundling the output of the tool in a NuGet package, so if that package got built on Windows the SQL script would have CRLF and if you built on Linux it would get LF. But that’s the nature of including any sort of text file in NuGet packages. So you can either select what OS you build on for the needs of the downstream consumers (hopefully none of the devops tooling cares?) or do a post-processing step before NuGet packaging.
as I’ve mentioned above the files are perfectly fine inside our repo and after a clean checkout. The line endings are already normalized.
Only after NServiceBus regenerates them on build the line endings are mixed up.
The problem is not our code but NServiceBus code that includes fixed crlf line breaks for the generated sql scripts.
To make it as easy as possible to reproduce and show my point, I’ve created a minimal repro sample on github. Just clone the repository on linux. It’s important to clone – and not just download the zip – so that git takes care of line endings and line ending changes become visible.
I’ve explained all the steps to reproduce in the readme.md file.
Here you can see the CRLF visualized as ^M$ on the left are caused by the new lines in the string on the right (snippet from the MsSqlServerSagaScriptWriter.cs)
The LF ($) originiates from the WriteLine that is happening on my linux machine when the Build is run.
Here is the \r\n that you mentioned above which also lead to CRLF. Replacing only them is not enough though.
For a thought experiment, let’s assume Particular would choose to build the package on a Linux machine.
The CRLF line breaks from the 1st screenshot would now be LF, for both Linux and Windows consumers of the library.
The CRLF from the \r\n in the 2nd screenshot would of course always remain CRLF no matter where the package is built or consumed.
I’ve added this thought experiment to try and explain that it’s also affected by the “implicit” line endings inside the strings.
I believe there are two possibilities to produce line endings that are consistent with the OS where the consumer piece of code is built:
a) Adjust line endings in the writers
e.g. replace \r\n with Environment.NewLine in the strings and use multiple writer.WriteLine to write the multi-line strings from the first screenshot.
I see that this might reading the sql statements in your code more difficult. That’s why maybe an option b) might be preferable: Normalize the line endings for the consumer OS after the file content has been finished, but before the files are written to disk as a final step.
Hope this makes sense.
We could also have a call if it’s easier to discuss. I’m in GMT+2