I am impressed how calm you stay about this. This is terrible. I just lost my home directory. All i did was start steam.sh with STEAM_DEBUG=1. I will investigate this and report back.
edit1: I suspect steam.sh got some bugs(does not check own variables) and when it tried to do scary things it crapped himself.
Line 468: rm -rf "$STEAMROOT/"*
edit2: It gets better. Seems on windows Steam is overeager too! https://support.steampowered.com/kb_article.php?ref=9609-OBMP-2526 (The warning part is interesting. Because everybody reads this before uninstalling...)
I agree, that line minimally requires an exists and not null check for $STEAMROOT
#scary!
As an ex programmer, that really makes me chuckle. Can I at least get an apology from whoever committed that comment without adding a fix?
This also happened to me a few weeks ago, my entire home was deleted by the steam.sh script.
introduced here Sep 10, 2013 https://github.com/indrora/steam_latest/commit/21cc14158c171f5912b04b83abf41205eb804b31 line 359
rm -rf "$STEAMROOT/"* could be evaluated as rm -rf "/"* if $STEAMROOT is empty
but what exactly caused this? i've symlinked ~/.local/share/steam to, so i am a bit afraid to start steam :/
pythoneer,
I believe the issue starts on line 19:
# figure out the absolute path to the script being run a bit
# non-obvious, the ${0%/*} pulls the path out of $0, cd's into the
# specified directory, then uses $PWD to figure out where that
# directory lives - and all this in a subshell, so we don't affect
# $PWD
STEAMROOT="$(cd "${0%/*}" && echo $PWD)"
STEAMDATA="$STEAMROOT"
This probably returns as empty which mean: rm -rf "$STEAMROOT/"* is the same ass rm -rf "/"*.
TcM1911,
that's my guess, too.
@keyvin @d00fy :
Line proceeded by # Scary! comment is in reset_steam() function, which is executed if and only if steam.sh is invoked with --reset as first argument.
Did any of you deliberately invoked that script with that option? If yes, why did you do it? What were you trying to achieve?
Removing user data is obviously wrong, no doubt about it. But if this happens only when user requests certain action, scope of that issue is somewhat limited.
Yeah, they kinda need a readlink in there.
STEAMROOT=$(readlink -nf "${0%/*}")
@Minio Not "only if". reset_steam is also invoked by removing your .steam directory, since that sets INITIAL_LAUNCH
@Minio A script accidentally running rm -rf /* is unacceptable in any scenario.
it is like bumblebee all over again!
https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/issues/123
I encountered Steam behaviour like with «--reset» for several times:
when I added «--reset» AND when I didn't. So — not «only if», can
confirm this, even having not deleted ~/.steam/ dir, too.
wonder what the code path is to hit that rm without --reset
Can confirm; I have Steam bounded in an SELinux context ("Steam") and SELinux spits out:
Context violation: process /home/indrora/.local/share/Steam/ubuntu12_32/steam is only allowed in context steam_context, attempted to remove /boot/efi/grub/efistub
Ooops. I'll write a patch and PR it :beer:
Does anybody have reliable repro steps for this? I can easily add the checks for STEAMROOT being empty, but I would also like to fix the root cause if possible.
It will definitely fail if you run steam.sh as bash steam.sh. I don't know if that's the cause in this case. In terms of root cause, I would say you should use set -e, set -u, and similar options in order to make the script less likely to silently ignore errors.
Using ${STEAMROOT:?} instead of $STEAMROOT would have helped, too.
(For those not familiar, ${FOO:?} is identical to $FOO except that it errors out automatically if $FOO is empty or unset.)
Which is the same thing that would have happened had the unnecessary '/*' not been there anyway, it would have errored out. Its not necessary because the rm was set to recursive already...
if [ ! -z "${STEAMROOT}" ]; then
rm -rf "${STEAMROOT}"
fi
Here is a patch which enables set -e, set -u, and a few others, and then fixes up all the places where undefined variables are expected to be (as far as I can tell): https://gist.github.com/rcxdude/1f6257e0a965147a462c
@rcxdude Come on. We are on github here. Do that in a PR please! Do not post whole patch files into issues... :-1:
@mablae There is no code on this repo, there is nothing to send in a PR against. A gist wouldn't have gone astray though :smile:
@rcxdude: Please link to a Gist.
@mablae How about instead of being a jerk, you link @rcxdude to some documentation.
@johnv-valve regardless of tracking down the cause of this, this rm line must be protected from future accidental gremlins due to the severity of the fail scenario.
@dannyfallon Oh, sorry then...
@sdt16 I am sorry. Thought the code was on this repo ... Didn't wanted to be a "jerk" :)
Does it happen only if you move ~/.local/share/steam ? #scary! :s
The idiomatic way to do this in Bash is to use default variables as in ,"${var:-/sane/path}" or "${var:?}" as was already mentioned. While using set -u or similar could have prevented this mistake, it's lazy and considered bad style.
If steam really wants to act like a package manager it should only delete files created by itself.
@soren121 +1
Shell scripts can also have tests, see shunit2. I wish I used it instead of making mini/naive one myself.
it's 2015; I think we can do better than complex badly written shell scripts.
rm is dangerous; you should never use rm ${macro}/
@d00fy Steam is essentially a package manager for your games.
@ju2wheels your snippet has a spurious 'D' in it, 'STEAMROOT' versus 'STEAMDROOT' -- so ${STEAMDROOT} will be empty and that code is going to end up starting at the current directory and doing a recursive delete from there.
Could be almost as bad depending what the current directory is. Let's hope nobody copy/pastes that snippet for actual use.
@mpnordland I think that's what he said.
I hope no one is running this as root
@d00fy I'm going to make the argument that while Steam is certainly at fault, you should definitely be using off site backups for this exact reason.
I hope no one is running this as root
On a typical desktop Linux system that would only make it marginally worse - reinstalling the OS is less of a problem than losing all your data from $HOME
@john-valve You are more than welcome to any log files that a data recovery service can get from the drive, as long as you give me a copy of everything. I do not have a large drive to undelete to, so the data that wasn't in the cloud is. Mad props for #Scary though
@nicatronTg Yes, I should need to have a complete back up rotation of dailies, four weeklies, and 12 monthlies so that I can feel safe and secure running steam for linux.
@DanielGibson Sure, as long as you didn't mount other partitions rw somewhere else
@carlosmcevilly even if they did it would be better than the existing code thats there ;-) , it will just fail and not take the world with it. But.... but... i fixed my typo ;-) , thx.
Hmm.. when I was copying .steam from an older installation to a newer installation of Kubuntu, I saw in stdout messages like "running rm -rf " when I was running it (after the rm -rf it installed Steam again with the 200MB download). Though of course I didn't lose any data.
@keyvin This is somewhat OT but to recovery your data, immediately stop using the external drive and run something like PhotoRec or TestDisk or if the drive has important files you can even use a program like ddrescue to copy the drive. If you haven't used the drive since the data loss then most of your data should be recoverable.
Note there is also protection against this within GNU rm itself. I.E. this would have protected the / dir at least:
rm -rf "$STEAMROOT/" && mkdir "$STEAMROOT"
But it's best leave out the / in any case as it's redundant
rm -rf "$STEAMROOT" && mkdir "$STEAMROOT"
Bash-isms are the problem here:
(cd `dirname $0`; STEAMROOT=`pwd`)
If dirname and pwd aren't in your "$PATH" then fuck you.
My condolences, @keyvin. I lost all my data like this in 1998 due to a SuSE Linux installation script having exactly this bug in it as well. Back then I lost my Linux, my Windows, and all my data and I only learned what backups are really for from that incident...
@TcM1911 Determining the path of the script being invoked, in a fully portable (w.r.t. platforms) and completely reliable manner, even in the face of symlinks, is a tricky problem and all too easy to get wrong. The only bullet proof way of doing it, of which I'm aware, is provided below (assumes bash); could be prepended to any script needing this functionality.
#!/bin/bash
script_path () {
local scr_path=""
local dir_path=""
local sym_path=""
# get (in a portable manner) the absolute path of the current script
scr_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && scr_path=$scr_path/$(basename -- "$0")
# if the path is a symlink resolve it recursively
while [ -h $scr_path ]; do
# 1) cd to directory of the symlink
# 2) cd to the directory of where the symlink points
# 3) get the pwd
# 4) append the basename
dir_path=$(dirname -- "$scr_path")
sym_path=$(readlink $scr_path)
scr_path=$(cd $dir_path && cd $(dirname -- "$sym_path") && pwd)/$(basename -- "$sym_path")
done
echo $scr_path
}
script_dir=$(dirname -- "$(script_path)")
@sindresorhus I'd disagree with using trash instead of rm because having to rely on node just adds complexity to systems that wouldn't otherwise need node.
It's also worth mentioning that most of the linux distros I've used recently have the --preserve-root flag already available...
I'd disagree with using trash instead of rm because having to rely on node just adds complexity to systems that wouldn't otherwise need node.
I know people disagree with that. That's fine. I was linking to the safeguard rm section.
I've moved my directory and symlinked it too, and I've thankfully not had such issues before. Regardless, as someone mentioned before, I'd strongly suggest adding test cases against such major bugs.
This big companies are so in the need of engineers that would even hire my grandma, and then shit happens.
In this context, how can i remove steam from my Linux without using steam?
As @d00fy said, it's amazing how calm you were about this, @keyvin. A great bug report it was too. Embarrassing as bugs like these are, it's a lot easier to take it on with reports like this one.
As others have pointed out too, this is an excellent bug for advocating using some BASH-strictness, I like to use this:
set -euo pipefail
This bug is also a good case for advocating TDD with shunit2. Make the steam script modular so that parts of it can be (unit) tested, write a test for this bug which fails and then fix it. We all do this in other "real" programming languages and there's no reason why we can't do this in BASH too. Hooking it up with CI servers like Jenkins is no problem either.
Tangentially related:
I assume all the people that moved this folder are running out of disk space/want to stuff the files elsewhere. Like myself. This is what I did on Windows just a couple days ago, I'd hope that Steam on Linux supports the same (hidden) option: http://www.rockpapershotgun.com/2012/09/11/finally-an-in-built-way-to-choose-steam-install-locations/
Basically:
Now you can pick the location during installation ("This game? Install to my SSD. That? Ah, large slow disk is fine"). You can also move games between locations (from $path1/SteamApps/common to $path2/SteamApps/common and that will 'just work' in nearly all cases).
So, maybe Valve should make that more accessible in the UI, bypassing the need of users to mess with the default install path?
Thanks for reminding me to always check shell scripts before executing them
@darklajid changing the destination can already be done without using -dev, console, and install_folder_ui.
steam -> settings -> downloads -> steam library folders
@synapse84 Whoa - and here I kept that bookmark around, treasuring my knowledge of hidden options. :) Thanks a lot!
Amazingly scary.
Stupidest bug I've seen in years.
git blame on that, who did the commit?
Valve is retarded on so many levels, they completely screw up how libraries are linked up in some vain attempt to make Linux a kind of Ubuntu ABI stable distro. Now this.. The fact that steam is not using chroot and Linux kernel namespace support to protect against buggy/nefarious applications is idiotic security practice.
Further, what is Valve doing for a proper review and audit system for patchsets and continues integration, github comments, is that it.. F* may as well write software via Stasi-book (Facebook) wall posts lol..
I just wanted, on behalf of whole internet, to tell that the whole world could learn a thing or two from you
@keyvin.
The "tone" used to describe the issue is informative and polite, raging, straight to the point.
well done!
:beers:
Classic Daily WTF: http://thedailywtf.com/articles/Bourne-Into-Oblivion
This is Bumblebee all over again.
@stryju Part of being a programmer now is being deluged in a sea of github repositories pretending that the software contained within works. Only after actually trying to use these projects, maybe even to the point where you start relying on them, do you realise half are garbage. After twenty or so such disappointments it's only natural then to remain calm in the face of yet another software project failure.
@xtraeme Mistakes happen, doesn't matter if you're competent or not.
@nuisanceofcats while this might be true, I'm still impressed how calm and polite @keyvin remained.
I went through a fair shareof github issues and this one caught my eye :smile:
@Bumrang You got this open source thing all wrong. There is no room for civil or mature feedback. You should try emulate Linus like @xtraeme is doing and be abusive to anybody whose work displeases you. Because clearly people don't make mistakes, their work is an embodyment of who they are. You either are good developer or your not, there is no growth.
@stryju Yeah you're right he is pretty calm, I think we should worship him as the new Buddha. @keyvin Have you always been so cool and collected, can you share your secrets with us? If someone wiped my system I'd be like, nowhere near as cool as you.
While using set -u or similar could have prevented this mistake, it's lazy and considered bad style.
It may not a good idea to knowingly write code that relies on set -u, but it helps prevent accidents exactly like the one this thread is about. It doesn't break any sane code. Turning it on is opting into some much-needed sanity checks.
@nuisanceofcats exactly! :beers:
Seriously, though... lets try to keep things civil. There can be any of a bunch of reasons for this having slipped by. It's especially obvious with how Valve works (joining and leaving projects almost at whim). The code could have been put in place by someone who's not even at Valve any more and folks picking it up just went with it because it was working. It's something that you could easily miss if you're not looking for it and didn't experience an issue with it. Anyone using Steam for Linux and following best practices and inspecting scripts before running them could have found this bug ages ago (myself included; I'm not saying I'm not equally to blame).
Think about how long it took for this to get a ticket. Everybody missed it for over a year.
@skybert set -e and set -u are recognized as poor coding practice. From bash-hackers.org:
set -e causes untested non-zero exit statuses to be fatal. It is a debugging feature intended for use only during development and should not be used in production code, especially init scripts and other high-availability scripts. Do not be tempted to think of this as "error handling"; it's not, it's just a way to find the place you've forgotten to put error handling. Think of it as akin to "use strict" in Perl or "throws" in C++: tough love that makes you write better code. Many guides recommend avoiding it entirely because of the apparently-complex rules for when non-zero statuses cause the script to abort. Conversely, large software projects with experienced coders may recommend or even mandate its use. Because it provides no notification of the location of the error, it's more useful combined with set -x or the DEBUG trap and other Bash debug features, and both flags are normally better set on the command line rather than within the script itself. Most of this also applies to the ERR trap, though I've seen it used in a few places in shells that lack pipefail or PIPESTATUS. The ERR trap is not POSIX, while set -e is. failglob is another Bash feature that falls into this category (mainly useful for debugging). The set -e feature generates more questions and false bug reports on the Bash mailing list than all other features combined! Please do not rely upon set -e for logic in scripts. If you still refuse to take this advice, make sure you understand exactly how it works. See: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected? and http://www.fvue.nl/wiki/Bash:_Error_handling
Correct me if I'm wrong, but AFAIK "$0" expands to the name the script has been invoked as, not the absolute path. (open a shell and try echo $0)
I guess this adds to the problem of not checking for unset variables...
$0 is useful for programs like busybox, that act differently depending on by what name they have been called.
Using it for filepath-magic OTOH opens yet another can of worms, as soon as there are symlinks involved: The regex can expand to a path that doesn't necessarily exist.
tl;dr: don't use $0 in paths.
@markgraf: $0 is the command the script was called with, for example emacs, or /usr/bin/emacs, or ../../bin/emacs. It's really just the first "word" of the command line. If you just want the name of the executable, use basename $0, if you want the full path, use readlink -f $0 (edit: except if $0 is a symlink, then readlink -f will return the full path to the symlink target).
actually $0 can be anything or nothing at all. See help exec in bash.
Everything is impermanent and transient. Especially bits on disk. No use crying over flipped bits.
I also don't want to get angry about it because steam for linux was a counter-thrust agaisnt microsoft turning windows into a walled garden with the app store. I didn't pay for steam for linux, and I appreciate that Valve is taking the time to make a proper port so we aren't all stuck running steam through wine.
If my root directory had to be sacrificed to appease the god of bugs, so be it. It'd be cool if I could get a special badge and an email apology from whoever added the #Scary! comment. That still makes me chuckle.
Came across a similar problem a few weeks ago when Steam started deleting files for unclear reasons; I killed the process as soon as I saw that. I first thought it was in its own dir, as I discovered that some games had been uninstalled but the maths didn't really add up. Now that I see this issue, I really wonder if I have lost important stuff (like backups of my work). I sure hope not but I'm pretty scared now.
Anyway, I haven't really understood from the long list of previous comments: is the issue fixed or not?
@markgraf, no not always, as it depends on invocation.
jordi@penyagolosa:~$ cat /tmp/meh
#!/bin/sh
echo "This is $0: $0"
echo "This is basename $0: $(basename $0)"
jordi@penyagolosa:~$ /tmp/meh
This is $0: /tmp/meh
This is basename $0: meh
Priceless...
comment before it goes hot.
Wow.
I think it is time to move Steam to a separate user and/or chroot, just in case.
@Korobochka I think that its best to do that for all games. I also only run Skype from a Windows VirtualBox. Its hardly as secure as Qubes but I think that proprietary apps that do a lot of stuff should be isolated in at least some minor way.
This issue has been open for 2 days without any response, fix, or apology from Valve? What the actual f**k?
Fire in the hole
It's like Sierra Half-Life 1 installer all over again. The installer had a default target of C:\Sierra\Half-Life. If you changed this to C:\Games\Half-Life and later you uninstalled Half-Life 1, the uninstaller removed C:\Games completely. Great achievement for Valve to bring such behavior back.
Just a hint: Did you ever check the amazing quality and documentation of Valve's Linux dedicated servers? It is horrific, I spent so many hours debugging this stuff.
Oh by the way: Valve is an US company deploying an automatic software installer onto your free software operating system. Would also be a great place for NSA to access your system.
@stratumnine As far as we know this has only affected one person and that person is chill about it. There's no need to get aggressive on behalf of these hypothetical people who it also messed up. You should learn from @keyvin, chillest brother alive.
Remember kids, before you rage in github think: "What would @keyvin do."
Praise be to lord keyvin.
PS Valve should provide offerings to keyvin.
This might become even worst than bumblebee... it can potentially erase any network volume that you have mounted at your filesystem. Imagine if you have your NAS drive mounted...
@nuisanceofcats no this happened to other people, too e.g. @onodera-punpun, @d00fy and other people reporting this on reddit r/linux
but nonetheless you are right about the tone especially these "w00t" ppl posting stupid pictures and posting nothing than bumblebee references which helped no one cuz there are so kewl.
@nuisanceofcats It has not affected one person, read the second comment for instance. I myself might have been affected by this as well. I lost tons of files for no apparent reason a couple of days ago. I am still investigating what happened and just found out about this.
I need to comment on this, because of yes. I use steam and omg!
Thanks for report this "scary bug"
Another genius.
Github is not a forum, if your comment is not related to the technical issue please stop posing and take it here: http://www.reddit.com/r/linux/comments/2sjjr3/warning_to_steam_users_dont_try_to_move_your/
but nonetheless you are right about the tone especially these "w00t" ppl posting stupid pictures and posting nothing than bumblebee references which helped no one cuz there are so kewl.
@pythoneer Yes, I'm kewl, what's your problem?
Bumblebee and this are not just bugs, they are gems. You can reference them in beginner's books where you say "don't do this, because that's what happens". I see nothing wrong with having some fun about it, especially if that causes people to remember it better.
I am doing exactly the same except that instead of using the Steam root folder as symlink, I use ~/.local/share/Steam/SteapApps and nothing got removed after the upgrade.
I think we should consider what @keyvin (praise be) would want before making any more comments on this bug. nuisanceofcats - first order keyvinite
@alexander-yakushev for fun posts and showing others how kewl you are pls visit other places like @ju2wheels mentioned. If you like to help in a serious way e.g. sharing experiences with this bug or reproducible behavior, feel free to post everything you know about. but this style of post is not helping but complicates to read through the post for ppl. who work with this information to track down and solve the problem.
@ju2wheels That code would seem to fix it. I don't see why a * was added to the rm command. If it wasn't there it would at least have errored out and preserved the files for those in OP's position.
On the other hand, the check should be made for the entire set of reset commands.
I would rather not have Steam installed until this is fixed. Is there an official procedure to uninstall Steam manually under Linux, like there is for Windows?
I'll just mention safe-rm - that's what I found after searching for a possibility to avoid such misfortune in vendor shell scripts altogether. It's a wrapper for /bin/rm that checks the given path against global and user specific blacklists. Sounds like a good way to tackle the problem at its root.
To those to believe its appropriate for software to fail today in this way, after literally decades of research into type-systems, test frameworks, fuzz testing, etc.. and so this is nothing short of brain damaged.
I don't even see an urgent advisory being pushed from Valve two days. So not only is this poor software, it's poor implementation of the development life-cycle and utterly egregious policy both technical and non-technical.
We need to seriously move away from this attitude of expecting software to catastrophically fail as if that's somehow acceptable. I realise the issue of complexity, hell even two uint64_t has more states than atoms of this planet, however we have very sophisticated tools and policy to mitigate or outright solve many of this idiotic issues that seem to keep coming up.
Less the technical side, we need to move away from this attitude of letting technical companies steal, spy and delete our data without any kind of recourse. It's ridiculous, Google for example is now pushing zero-day exploits since Microsoft was so negligent in acting to fix its security issues. Similar stories for Apple. I see no clear security and advisory information for this software at all. I also see this software not following best practices in modern security either, at all.
Good programmers think about algorithms (i.e. check the thing your about to delete, Jesus); Great programmers think about type-systems and the Curry Howard correspondence; Fantastic systems engineers think about all these aspects and policy to cover non-technical issues also.
Maybe Steam should be using less hard coded shell script which is completely shell dependent and start using high-level tools to do things directly. Shell script is really for short jobs that happen one or two times, they are not really for production grade software in its general mode of operation. Even build systems such as CMake, SCons, Cabal, etc..learnt shell script sucks in generality long ago!
@kkriehl - safe-rm would probably save us here. Since we're calling rm -rf /* the shell globs it up and rm gets the arguments ( /boot /etc /dev /home /usr ... ) and as such isn't protected. rm as it stands has protection against rm -rf / -- you have to pass it --no-preserve-root if you're going to do that.
Problem is, that's another dependency. Unless VALVe includes the wrapper statically.
Apple had a similar issue with an iTunes installer about ten years ago - if your disk name included a space, it would fry your iTunes. Same problem - bash expansion issues.
bash is not a good tool for this purpose. EIther have people audit each line of the bash scripts, or write it in a high-level language and include a lot of checking still...
Suggestion:
1.) Don't use bash, C is more than capable of handling this functionality. And you remove a dependency ( bash is now a security risk ).
2.) And even more so, it might be prudent to NOT delete anything, and just create a new directory with a uuid/timestamp and change a symlink. I think anyone using linux can write their own cleanup script if they feel the need.
For those of you saying Valve didn't respond to this yet, I suggest you search this bug for johnv-valve and MrSchism.
Incidentally, it's also just before 8am PST (Valve's timezone), so chances are none of the Valve developers are currently at work or even looking at this thread at the moment. Or have for the past 16 or so hours.
oh my what a bug.
Shouldn't "As a user I want to move my Steam folder to another media." be a regularly tested user story? Games are big and SSDs are small, so this should be quite common.
@Indrora You're right and I maybe should have mentioned that I don't think safe-rm would be an adequate solution. Not at all. But I think it is mentionable as a possible general precaution to avoid loosing data because of careless scripts for worried visitors like myself ;)
I'm seriously asking myself more and more why I would use steam. Why didn't you consider to at least have a "- d" check before each removal? I mean, STEAMDATALINK is also empty. WTF, dudes. WTF. This is seriously a problem for my system and will be put into a chroot by me from now on.

Well this is interesting...
https://github.com/lrusak/steam_latest/commit/21cc14158c171f5912b04b83abf41205eb804b31
Is now 404'd. What a cowardly move.
rm -rf $dir/*
is just a stupid and dangerous way to do:
rm -rf $dir/
Only the former will preserve dot files (or not, depending on shell options, shell interactivity etc.)
I was stung by this bug two days ago.
Good thing I manually installed steam in a semi-isolated way, under a very unpreveleged user. So hardly anything of value was lost.
@Xaekai - I forked the repo before it died, plus patched the problem in some places: https://github.com/indrora/steam_latest/commit/e0686814c0dca462007b6343c763483071dba591
readlink is not reliable, it is not part of the POSIX essentials (but part of Debian's coreutils). I remember that it used to be in the LaTeX package on my old SuSE.
You can't set variables in subshells: (@seanchannel)
$ a=1;(a=2); echo "$a"
1
Your example should be
foo="(cd "${0%/*}" && pwd)"
Also $0 is not directly affected by argv[0]:
$ cat foo.sh
#!/bin/sh
echo '$0: '"$0"', $1: '"$1"
/usr/bin/dirname "$0"
$ sh -c './foo.sh "$@"' whatever second
$0: ./foo.sh, $1: second
.
$ sh -c './foo.nothere "$@"' whatever second
whatever: 1: whatever: ./foo.nothere: not found
Yet another problem:
$ cat bar.sh
set -x
foo="(cd "${0%/*}" && pwd)"
cd /
ls -l "$foo"
$ ll /proc/self/cwd
lrwxrwxrwx 1 7eggert 7eggert 0 Jan 16 19:01 /proc/self/cwd -> /tmp
$ busybox sh /proc/self/cwd/bar.sh
~/.local/share/Steam is a symlink here too, so I'm not overly happy if it's a precondition for getting bitten by this. When are these sanity issues in the script going to be fixed so that we can actually safely run steam?
For now I commented out the rm -rf "$STEAMROOT/"*line and did chattr +i ~/.steam/steam/steam.sh to prevent steam from modifying it.
If you need a lot of shell scripting... hire someone who knows shell scripting.
@keyvin I have managed to reproduce this, can you tell me if this might describe what happened on your machine?
copy ~/.local/share/Steam to an NTFS drive.
rm -rf ~/.local/share/Steam
symlink ~/.local/share/Steam to the NTFS drive
When I did this on Ubuntu 14.04, all the steam scripts and binaries on the NTFS drive were stripped of the executable bit. So the function check_bootstrap() in /usr/bin/steam thinks there is no steam installed and gives you an error. Trying to rebootstrap or anything will fail due to the same lack of executable permissions on the NTFS drive. Still, nothing should be deleted at this point.
Now you might try to skip /usr/bin/steam and run ~/.local/share/Steam/steam.sh directly. Again, this will fail due to lack of executable bit on steam.sh. chmod +x ~/.local/share/Steam/steam.sh doesn't work either.
So now you're really annoyed and you open up a terminal, cd ~/.local/share/Steam and run "bash steam.sh". This is what triggers the horrible bug, because the STEAMROOT="$(cd "${0%/*}" && echo $PWD)" incantation in steam.sh can't handle $0 being "steam.sh" instead of something like "./steam.sh". Launching the bootstrap fails, and we try to reset steam, but since STEAMROOT is wrong it ends up doing the rm -rf /
This is the only way I have found so far to trigger this bug. If you think there is some other sequence of events that happened on your machine, please let me know.
I plan to fix this by using STEAMROOT="$(cd $(dirname $0) && echo $PWD)" as well as adding extra checks for STEAMROOT being blank and the general improvements suggested by @rcxdude
I only ran steam, but I launched from a shell with no options. I had
probably ten years of cruft in my .bashrc and .bash_profile because I would
add stuff and never delete it. It is a pretty severe outcome, but I do not
know what caused it, which is why I was so calm in the report. I figured it
might be a combo of what I had done to my system combined with something I
had done long, long ago. I updated the bug to say I had customized all
kinds of stuff to hopefully keep people from continuing to make worthless
contributions.
If it makes a difference, I had /bin/sh linked to /usr/bin/bash instead of
dash, maybe some other symlinks too but I no longer have my bashrc and
bashprofile.
I do not know if that line everyone is pointing to gets called in the
process of launching steam, it may have been the culprit, but I can't even
set up my environment the exact way I had it to find out because I didn't
upload everything to the cloud.
Thanks for looking into this. I really didn't expect it to get
sensationalized like this. You might try contacting some other people that
contributed and ask them if they ran the script as well or not to get a
better idea of what caused it.
If there is anything else I can tell you so people don't quake in their
boots to run steam, please let me know. Something failed, and it failed
spectacularly for me, but it might not even be reproducible without my
exact config and system, so all you can do is guess how it failed so
spectacularly.
Also, thanks for working on steam for linux!
On Fri, Jan 16, 2015 at 2:25 PM, johnv-valve [email protected]
wrote:
@keyvin https://github.com/keyvin I have managed to reproduce this, can
you tell me if this might describe what happened on your machine?copy ~/.local/share/Steam to an NTFS drive.
rm -rf ~/.local/share/Steam
symlink ~/.local/share/Steam to the NTFS driveWhen I did this on Ubuntu 14.04, all the steam scripts and binaries on the
NTFS drive were stripped of the executable bit. So the function
check_bootstrap() in /usr/bin/steam thinks there is no steam installed and
gives you an error. Trying to rebootstrap or anything will fail due to the
same lack of executable permissions on the NTFS drive. Still, nothing
should be deleted at this point.Now you might try to skip /usr/bin/steam and run
~/.local/share/Steam/steam.sh directly. Again, this will fail due to lack
of executable bit on steam.sh. chmod +x ~/.local/share/Steam/steam.sh
doesn't work either.So now you're really annoyed and you open up a terminal, cd
~/.local/share/Steam and run "bash steam.sh". This is what triggers the
horrible bug, because the STEAMROOT="$(cd "${0%/*}" && echo $PWD)"
incantation in steam.sh can't handle $0 being "steam.sh" instead of
something like "./steam.sh". Launching the bootstrap fails, and we try to
reset steam, but since STEAMROOT is wrong it ends up doing the rm -rf /This is the only way I have found so far to trigger this bug. If you think
there is some other sequence of events that happened on your machine,
please let me know.I plan to fix this by using STEAMROOT="$(cd $(dirname $0) && echo $PWD)"
as well as adding extra checks for STEAMROOT being blank and the general
improvements suggested by @rcxdude https://github.com/rcxdude—
Reply to this email directly or view it on GitHub
https://github.com/ValveSoftware/steam-for-linux/issues/3671#issuecomment-70307541
.
@johnv-valve:
I just remembered a detail: I might have mounted the drive with an fmask set that would allow execution of all files.
Just don't write these kinds of scripts in BASH / SH. Too bug ridden. Use python. Every distro now comes with Python because so many support scripts are written in it. Why not PERL? Because PERL has a strict mode as well, which means its default mode of operation can have braindead bugs like this one.
Too many ways to get quoting and if-tests wrong in Bash.
I don't know of a language that prevents you from writing bad code.
The code is not the entire problem. Lack of tests/testing seems to be an issue as well.
Most Times you call GNU rm, you should use "rm -- ".
like: rm -rf -- ${my_checked_path_var}
Thank you.
I don't know of a language that prevents you from writing bad code.
This has to be the worst example for that. Bash ignores errors and undeclared variables. Ignored errors and undeclared variables are bad code, and most languages besides bash prevent one from using that type of bad code.
@robin-wittler You need to quote the variable, or else any spaces will cause it to be interpreted as several filenames. (The -- does help it work with paths that begin with -.)
@robin-wittler : Directories may contain spaces.
my_checked_path_var="/tmp/foo /home"
mkdir "$my_checked_path_var"
ls -- ${my_checked_path_var}
@AgentME, @7eggert ... yes you are absolutly right. I owe you all a beer. ;)
Should i mention IFS? ;)
Anyway, using quotes is always the less confusing way and it just works.
@7eggert Wrap code blocks with `````. Like this:
```
foo
bar
```
It will look like this:
foo
bar
johnv-valve wrote:
I plan to fix this by using STEAMROOT="$(cd $(dirname $0) && echo $PWD)" as well as adding extra >> checks for STEAMROOT being blank and the general improvements suggested by @rcxdude
May I also suggest looking in the calculated $STEAMROOT, for presence of one or more items that can be expected to be present there, such as steam.sh, bin_steam.sh, and/or steamapps, before doing the remove?
If such items are not present, then you don't want to be nuking it, regardless of how carefully you computed the $STEAMROOT location.
This is pretty bad btw (from the current Steam beta):
if [ "$STEAMROOT" != "" ]; then
rm -rf "$STEAMROOT/"*
fi
You can just do if [ "$STEAMROOT" ]; then
Also rm -rf "$foo"/* is too volatile to use in a script regardless or anything.
Use find:
if [ "$STEAMROOT" ]; then
find "$STEAMROOT" -mindepth 1 -delete
fi
And the suggestion to use readlink (STEAMROOT=$(readlink -nf "${0%/*}")) is correct. Plz. The way it is done currently is abysmal.
I think it is actually more beneficial to check if it is a directory, so:
if [[ -d "$STEAMROOT" ]]...
(via FlutterRage from gamingonlinux)
It's a commentary on the sad state of shell scripting. It's hard to get right and few people really understand what they're doing; I sympathize with the developer who made this mistake.
I ran steam.sh through ShellCheck and, while it does not pick up on this issue, it does note a number of other bad practices. A tip for the amateurs: If you don't feel confident in your shell-fu. use validation tools to help. Or just ask someone who is an expert.
@vdrandom you know / is a directory right?
[r3pek@trinity ~]$ [[ -d / ]] && echo "is dir" || echo "not dir"
is dir
[r3pek@trinity ~]$ [[ -d /tmp/steam_chrome_shmem ]] && echo "is dir" || echo "not dir"
not dir
-d doesn't solve anything
Ugh, this is really scary stuff. Especially sad since it would never have happened if they had used Perl instead of Bash.
@r3pek yes, hence it's [[ -d "${STEAMROOT}" ]], not [[ -d "${STEAMROOT}/" ]]. The problem was with the lack of check whether it's empty. That test will also ensure that it is not only not empty, but is also a directory.
And that slash on the end of it was part of the hard code, not a variable.
@vdrandom yes, you're right ;) totally missed the difference :P
I can't reproduce this on Fedora, I don't get an selinux warning either. Anyone tried reproducing this in an VM?
For what it’s worth my ~/.local/share/Steam has been a symlink to another ext4 partition for 2 years, and apparently Steam hasn’t deleted any of my files.
But the OP is talking about ~/.local/share/steam; I don’t have a directory by that name (note the lower-case 's').
Checking that "${STEAMROOT}" is a non-empty shell variable, that resolves to a directory, is not enough, in my view.
If STEAMROOT=/, then that's a non-empty setting resolving to a directory. But I don't want to remove all files in any directory below /, limited only by which directories I have write permission in .
If a script that most users will run blindly (without having carefully read and understood it, or even being competent to do so) is going to remove an entire directory sub-tree, then there should be a marker file in that sub-tree, that marks it as "one of those sub-trees which can be so deleted."
Such a check would, amongst other things, help guard against a confused or malicious setting of STEAMROOT in the environment in which steam.sh is invoked, as in "STEAMROOT=/ bash steam.sh"
I recommend that steam scripts take these steps for all usage of such a variable as STEAMROOT:
That file might have some such name as "STEAMROOT_marker_file.README.txt", and might have a short paragraph of text stating that "All files in and below the directory containing this STEAMROOT_marker_file.README.txt file are controlled by your Steam installation, update and configuration scripts. Such files may be removed or modified without notice. Don't place anything else in this directory or below."
BTW: I frequently symlink start scripts into ~/bin.
Is there any comment from valve about this "bug"?
This is still strange, the command "rm -rf /" cannot work from the steam script because it needs super user privileges and also the additional argument "no-preserve-root".
@karbrueggen, the fix has been already pushed into the beta, what other comment do you expect?
@fcole90 "rm -rf /*" (note the asterisk), however, does not need super user privileges, nor is it hindered by --preserve-root.
And while it can't delete the operating system files without super user privileges, it is perfectly capable of erasing all personal user data on the system. Which is exactly what @keyvin reported.
the fix has been already pushed into the beta, what other comment do you expect?
Uhm. How they are going to try to prevent this kind of mistake from happening again. QA, peer-review, tests, whatever?
Ideally they would drop shell scripts. Python has everything to do this
stuff safely and it is standard to the python interpreter you ship with the
software. Yes, they can include an entire python interpreter in their steam
application. You really can't make assumptions on Linux about anything when
it comes to cross distribution shell scripts.
It would have been OK if it had just crashed, without even logging. That is
failing gracefully. What it did was fail spectacularly. I think the
developers should consider using a better scripting language, unless the
bash stuff was just a prototype that survived into Beta.
Thanks for bringing us steam for Linux!
On Jan 18, 2015 1:44 PM, "Julian Ospald" [email protected] wrote:
the fix has been already pushed into the beta, what other comment do you
expect?Uhm. How they are going to try to prevent this kind of mistake from
happening again. QA, peer-review, tests, whatever?—
Reply to this email directly or view it on GitHub
https://github.com/ValveSoftware/steam-for-linux/issues/3671#issuecomment-70419895
.
I think the developers should consider using a better scripting language, unless the bash stuff was just a prototype that survived into Beta.
You can do that kind of mistake in pretty much any programming language (some just make it harder, especially typesafe ones). In python you can also open subprocesses with a true shell context and mess up whatever you like. And people do that.
The reason most (source) distributions have a sandbox and a lot of abstraction in their package manager is because they don't trust any scripts/build-systems. Through the package manager it is usually not possible to remove files that do not belong to the package, because the files that belong to the package are recorded in a database.
So, without any such concept and abstraction model that only does predictable things instead of a quickly hacked up shell/python/whatever script... this can happen again, regardless of language or build system.
a change of language just gets you a change of bugs. this should be coded more responsibly and adhere to POSIX standards. we also need a real, hardened POSIX shell that is not just bash playing shadow puppets.
The reason most (source) distributions have a sandbox and a lot of
abstraction in their package manager is because they don't trust any
scripts/build-systems. Through the package manager it is usually not
possible to remove files that do not belong to the package, because
the files that belong to the package are recorded in a database.
Oh yeah, things like deb packages don't rely upon scripts and people
haven't had any trouble about them. Yes. And I didn't receive a gift
license key from a package maintainer for helping as a remote 3rd-party
to resolve such an issue happened to random user on IRC recently. Yeah.
Not possible to remove files or do crappy #Scary things with
system-wide privileges.
Does this affect Fedora, because I can't find a steam.sh on my system. I have a steam package from rpmfusion.
$ rpm -q steam
steam-1.0.0.47-2.fc20.i686
my /usr/bin/steam does not have any reference to reset or STEAMROOT or a wildcard "rm -rf" (it does have some rm -fs of specific files as well as an rm -fr $LAUNCHSTEAMPLATFORM/steam-runtime which seems a bit safer) . it contains the following line:
export STEAMSCRIPT_VERSION=100047
@ahamid I do have it under (slightly outdated) Fedora 20.
$ uname -r
3.17.8-200.fc20.x86_64
$ rpm -q steam
steam-1.0.0.49-3.fc20.i686
$ cat .local/share/Steam/steam.sh | grep Scary!
# Scary!
My steam script seems to be a bit newer than yours:
$ cat /usr/bin/steam | grep STEAMSCRIPT_VERSION=
export STEAMSCRIPT_VERSION=100049
About Steam:

I believe I have Steam from RPM fusion as well.
fcole90 commented 12 hours ago
This is still strange, the command "rm -rf /" cannot work from the steam
script because it needs super user privileges and also the additional
argument "no-preserve-root".
I beg to differ. That "rm -rf" command is recursive, silently forced, from the root '/' down.
Sure, whatever is directly in the root '/' directory is probably safe, because very few user systems are so badly configured that the root directory is user owned or user writeable (and those users have already decided to practice sky diving without a parachute.)
However, "rm -fr /" will traverse all mounted file systems, silently removing every file (no matter the file's permissions or ownership) in every directory, for any directory that allows user write permissions, and is below a directory path that is searchable (higher level directories are executable.)
Very few users have a backup strategy in place that will recover from that sort of damage without great pain and loss.
@Bengt Ow! You're right, I thought I checked everywhere for steam.sh but it is there under .local/share/Steam. Is there an interim safeguard - I feel like commenting this line out entirely. Actually the whole script is littered with rm -rf commands.
@ahamid See: https://github.com/ValveSoftware/steam-for-linux/issues/3671#issuecomment-70298406 ... In contrast, just left everything as it is for now, because it seems to me that fiddling around with Steam's files might cause more trouble. I am aware of the Steam's current volatile nature, make backups of my most valuable stuff and wait for an official fix.
It's better to rewrite the script in another language. Python should be a good language for this. It's not good to have unmaintable scripts like this. No one would read the code and no one want to do changes on the code, because it works anyway.
@sosi-deadeye, and that would help exactly how? It is entirely possible to write bad and unreadable code in virtually every language out there.
@Valve: I know this stuff is opensource, but you don't have to copy all of my code :)
An even better fix, btw, would be to hardcode such things.
Guessing the script's location reliably is basically impossible for every case; it's a bad practice overall.
That would help to do it in the right way. Writing good readable shell
scripts is nearly impossible. Did you ever looked inside init-scripts? They
are doing lot of magic with including sources into the init scripts. But
the code ist unmaintainable. For example the srds_run is horrible to read.
I do understand the code, but never want to change anything there.
Jack Frost [email protected] schrieb am Mo., 19. Jan. 2015 12:25:
An even better fix, btw, would be to hardcode such things.
Guessing the script's location reliably is basically impossible for every
case; it's a bad practice overall.—
Reply to this email directly or view it on GitHub
https://github.com/ValveSoftware/steam-for-linux/issues/3671#issuecomment-70479202
.
Init scripts used to be small and maintainable. But if you add crude logic to also configure the application by collecting various information from around the system, you'll get a program containing tons of crude logic in any language.
Besides, system($PROG_RM." -rf ".$STEAMROOT."/*") would not be better.
I don't get why '/*' is even needed. How better is it compared to { rm -R "$STEAMROOT"; mkdir "$STEAMROOT"; }? Using wildcards for removal, especially recursive, is a very, very dangerous thing to do to begin with, not to mention that -f is also barely ever needed.
Redundant, but:
if [ "$STEAMROOT" != "" ] && [ "$STEAMROOT" != "/" ]; then
rm -rf --preserve-root "$STEAMROOT/"*
fi
You could also add checks for typical linux directories:
/{usr,var,bin,sbin,etc}
You get the point here. Might not be a bad idea to force STEAMROOT to be inside of ~/ as well.
EDIT: Probably good to have both checks as not everyone is necessarily using GNU rm.
Oh yeah, things like deb packages don't rely upon scripts and people haven't had any trouble about them.
I don't think debian is a good example for QA.
The point was to move away from uninstall/cleanup methods that have undefined behavior and rather look up files from an internal database and _remove known files only_. That is a completely different concept.
This is just an example for: underestimated the problem to be solved. And Linux distros have decades of experience with this problem. Just use it. It's open source.
Oh yeah, things like deb packages don't rely upon scripts and
people haven't had any trouble about them.I don't think debian is a good example for QA.
I just reminded you of the other side without which the system you
mentioned doesn't work. Likely, RPM too, as far as I can recall.The point was to move away from uninstall/cleanup methods that have
undefined behavior and rather look up files from an internal database
and _remove known files only_. That is a completely different
concept.
Yes, I'd like this idea. If I don't remember trashed Win Registry and
all those Program Files folders with useless abandoned things the
initial installer database doesn't contain. This is not a panaceia,
sigh.
I just reminded you of the other side without which the system you mentioned doesn't work. Likely, RPM too, as far as I can recall.
You really miss the point. This is not about being bug-free, but about making fundamental mistakes less likely by introducing concepts that are more strict and allow less random effects (and that doesn't just involve a different language). That is pretty basic and I shouldn't have to explain it.
Repeating the whole history and all experiences of existent, widely tested solutions is valid, but not really smart. That's why we are here.
The current "fix" for this bug is still wrong.
Yes, I'd like this idea. If I don't remember trashed Win Registry and all those Program Files folders with useless abandoned things the initial installer database doesn't contain. This is not a panaceia, sigh.
You are just reminding us that windows is broken and mix it up with other arguments. That's not really a coherent argumentation.
The current "fix" for this bug is still wrong.
Here's where I agree.
All bug fixes from Steam/Valve will be wrong unless they do a cultural change in how they write their software.
rm -rf /*@rpdelaney I don't agree with that. I think that using set -e and set -u is actually a very good coding practice. And the best example if this bug.
When one of the commands that your script runs returns an unexpected error, IMHO is always better to have the script aborting than to continue and risk causing some very undesirable situation (like wiping all your files).
For example, the Debian Policy Manual states that all maintaner scripts should either check every command for the return value or run with "set -e" defined (those are the scripts that are executed when a package is installed or removed: postinst/postrm/etc..):
Every script should use set -e or check the exit status of every command.
https://www.debian.org/doc/debian-policy/ch-files.html#s-scripts
@ryanpcmcquen Don't compare paths with =, use -ef:
if [ $EUID -eq 0 ]; then
echo "This script should not be run as root!" 1>&2
exit 1
fi
STEAMSH=$(readlink -e -- "$0")
STEAMROOT=$(dirname -- "$STEAMSH")
if [ ! -d "$STEAMROOT" -o "$STEAMROOT" -ef / -o "$STEAMROOT" -ef /home -o "$STEAMROOT" -ef "$HOME" ]; then
echo "Illegal STEAMROOT: $STEAMROOT" 1>&2
exit 1
fi
Warning: This code is untested.
@panzi :+1:
What does -ef do?
@ryanpcmcquen
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
[ FILE1 -ef FILE2 ]
True if FILE1 and FILE2 refer to the same device and inode numbers.
I dont usually get critical in bug reports but seriously????? Just checking for null then deleting everything??
if [ "$STEAMROOT" != "" ]; then
rm -rf "$STEAMROOT/"*
fi
what if $STEAMROOT is a space char, ".." or a whole bunch of other possibilities. This still an untested amateur hour waiting to happen. There should be a list/db of items to delete and those should be the only possible items to ever delete with this script.
@cebericus $STEAMROOT is not going to have just any arbitrary value in it. An error in it being set leads to it being an empty string.
Sorry, but it does not matter. You cannot predict all future usages or changes to the script and depending on a discontinuous section of the code to insure that rm -fr behaves correctly is bad design and bad practice. Better safe than sorry.
@gdrewb-valve do you already have a plan for fixing that problematic maintenance script?
I am scared about further executing steam.sh after reading it as i saw many pitfalls in the code which can lead to undefined behaviour (or chaos).
I agree with @cebericus. Steam needs an installer/deinstaller application supported by a database where every installed file is registered, that would be a proper fix. "rm -r" is not an uninstallation routine.
Don't make a DB, please.
To anyone who suggests it: If you wanna be "this much safe" go back to Windoze. You have your db, and just gotta format every 6 months.
We just need better checks for rm -rf
@keyvin, amazing bug report by the way. A lot of people here could learned a few things from you. Hope you get to try something new after wiping your configuration, 10 year's is a long time and I surely would take the chance to try out a lot of new stuff.
On the matters of blaming: Don't "blame" developers for bugs, this will bite you in the ass sooner or later. EVERYBODY makes mistakes, at least a few of them. If you make only ONE and it wipes an entire system, you're still fucking amazing, and one person is allowed to hate you.
About changing the language: I completely disagree. I think we need better checks for where the executable is and where steam files are. I also think this shouldn't be a script in any language, this should be coded "properly", in whatever language, and not rely on anything, rather detecting all folders and files through brilliant coding. :D
If that's impossible, then the language doesn't matter, what matters is fixing every little bug and improving the errors. Introducing a bazillion python bugs to the "new script" is definitely the last thing we need.
Lastly, thanks to Valve for trying to make steam work in our insane Linux World (How many distros supported already? Runs flawlessly on Arch Linux, Manjaro, Bridge, Debian and Ubuntu, by the way) and all my loving to the developers who have to read stupid people talking as if their code in a GitHub comment would have fewer bugs than Valve's "because they are smarter that the entirety of Valve developers".
The only "database" needed is hardcoding ~/.local/share/Valve_Steam/ into the application, and maybe testing for /opt/Valve_Steam/. Linux does support symlinks, therefore hardcoding is no problem.
STEAMROOT=~/.local/share/Valve_Steam/
if [ \! -d "$STEAMROOT" ]; then
if [ -d /opt/Valve_Steam/ ]
then STEAMROOT=/opt/Valve_Steam/
else
mkdir -p "$STEAMROOT"
if [ \! -d "$STEAMROOT" ]
then echo "cannot create $STEAMROOT"; exit 1
fi
fi
fi #untested
This may still go wrong, but it's by shooting your own foot, not by a script having unexpected behavior.
BTW: I suspect ~/.local/share is the wrong location, since "share" means "these data are the same across different CPU architectures, no need to have a different one on arm or sparc"
https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
@7eggert, it's XDG directory structure, see http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html. $XDG_DATA_HOME is used because there is no standard for storing arch-dependant binaries, libs and so on within $HOME.
Then XDG is to blame for being incomplete and bad.
@7eggert according to the Wikipedia citation you linked, /share is "Architecture-independent (shared) data." I can find no reference to ~/.local/share, nor to a standard meaning for share generally.
There is some basis for a precedent though, under /local: "Tertiary hierarchy for local data, specific to this host. Typically has further subdirectories, e.g., bin/, lib/, share/."
Along those lines, it would seem perfectly logical that if /local is "Tertiary hierarchy for local data specific to this host", then ~/.local/ would be "Tertiary hierarchy for local data specific to this user." And thus ~/.local/share is "Tertiary hierarchy for local data specific to this user that is architecture independent."
It's not clear how the XDG standard is "to blame for being incomplete and bad." It looks more like the XDG standard did not agree with your preconceptions about what share should mean when abstracted from any meaningful context.
You're describing my way of thinking. "share" == "shared data across systems".
My view about XDG is "It should work as intended even if I have $HOME mounted on my Mac and my PC, and you know why your 'solution' is intentionally and unnecessarily wrong."
I'm not persuaded, but on second look this seems really off topic for this bug report. Sorry for continuing the derail.
@frnco Just as a side note: Using a DB is the Linux way. See all package managers. Some of them even transactionally install/remove packages. Also a typical Linux distribution has a release cycle of 6 months, meaning you have to reinstall your Linux system every 6 months (unless you think dist upgrade is not too risky for you). Sorry for being off topic.
@frnco
To anyone who suggests it: If you wanna be "this much safe" go back to Windoze. You have your db, and just gotta format every 6 months.
You probably don't know, but literally any linux distro package manager uses a DB.
It seems what we want to do is confirm that the folder steam.sh wants to delete on a reset is the folder steam made in the first place, isn't this easy when you use an empty file as a marker? In pseudo-code, it would be: if test ( "$STEAMROOT/.steam.keep" file exists ) then delete folder contents, else tell user that this sanity check has failed and manual intervention is required (explicitly die here), end if. You add this .steam.keep file by either using the touch command or adding it to generic steam user download. Most users should not care you added a handful of filesystem bytes to prevent the bad scenario.
This should exclude all not target folders unless the user is willfully killing their own system.
@Tele42 this doesn't really tell you if you just wiped a lot of user files as well, but it's certainly better than just checking a variable for null
@hasufell The upside is that it would seconds to minutes of dev time to implement.
@panzi I user Arch, so it's rolling release, I never reinstall. And I think no worries about off-topic on this case, it's pertinent. And you do have a good point, as @hasufell . I shouldn't be judgemental, using a DB is not a bad thing necessarily.
Still, I don't think it is a great way, especially in this case. I can see things easily going awry with a DB, especially considering Steam is, in a way, a Package Manager, and one with a bazillion games that each can do a lot of stuff on the system.
Steam would have to keep track of every file it had ever downloaded/created/edited/etc, and, considering the amount of games on Steam, I think that would take too long to code, raise complexity too much (And needlessly), take a LOT of disk space and a lot of time to run, plus it would increase the risk of bugs.
I think the best idea so far is testing the folder, checking if it is a valid path, if it's not a system directory, if it exists and if it has some specific files in it, and then deleting the tree. Adding a README.txt telling people not to copy files over there can also be great, but even Steam on Windows erases, for example, game mods if you tell it to check for corrupted files, so I don't think that's so bad. At least we're making sure Steam only "messes" its own directories.
Perhaps Steam should use some of the solutions from package managers. Perhaps that is the best way. I just think we need something more feasible for an immeadiate solution. And developing a system for tracking files plus a DB for those files because of one rm -rf deep in a bash script that went awry one time seems a bit overkill to me. Much more feasible to check before the rm -rf
Yes, it cannot keep track of all the game files, because the games might create/change their files in an unknown manner to steam. But it could keep track of it's own files and of the game directories. Just recursively wipe the game directories without following symlinks, but exactly delete only known steam files. Anyway, I think better checks (like I wrote above) would be good enough.
@panzi I think "good enough" and "quickly" are the things we should be looking for in an answer to this bug. :D
Steam would have to keep track of every file it had ever downloaded/created/edited/etc, and, considering the amount of games on Steam, I think that would take too long to code, raise complexity too much (And needlessly), take a LOT of disk space and a lot of time to run, plus it would increase the risk of bugs.
First, there are already existent solutions for this and e.g. ChromeOS realized it can just use them. There is no reason to code something like this from scratch.
Second, I don't know what you mean with complexity exactly. Algorithmic complexity, LOC?
The argument of disk space is simply wrong. A DB can also be a simple text file and most package managers use plain text files.
You can test it yourself:
cd /steam/root/folder # make sure it worked, lol
find . -type f -exec echo '{}' >> mysteamdb.txt \;
du -sh mysteamdb.txt
The argument of runtime is just weird. I'd rather have it take 20 seconds more and be much more safe.
The argument of risk of bugs is even weirder. Shell scripts that are based on live filesystem checks and random variables are so full of side effects and undefined behavior (if you have dealt with autotools, then you know that shell definitely does have undefined behavior) that an abstraction layer is a very good solution to this problem. Sometimes a proper solutions takes more LOC. That's a fact.
@hasufell If you want to be really exact use:
find . -type f -print0 >> mysteamdb.db
This will separate file names using nil bytes, because a newline is a valid character in file names under Linux. You can then do things like this:
xargs -0 < ~/mysteamdb.db ls -lh
@hasufell I was thinking about code complexity. More code, more functionality.
Your other points are indeed valid. 20 seconds is not horribly bad, and that's an engineering choice. I just think we should focus on the best bugfix, and allow engineers to develop the best solution they think they can, because we're not gonna design the ideal solution in here.
"undefined behavior" == "Don't do that then", not "find out what this version of that shell does in that corner case and use it"
@frnco it wouldn't need to worry about game files. We're talking about the Steam client only. It would only have to keep track of the Steam client files.
We shipped a one-line fix to avoid the one situation where we could reproduce the problem. We are still working on some more comprehensive changes, but we wanted to get a fix out there quickly in case this somehow hit anybody else.
If anybody knows how to actually reproduce this bug, please post the steps here or email me directly. So far we have not been able toe reproduce it and I would hate to be barking up the wrong tree if the problem is really somewhere else.
Also, I'd appreciate it if people would not use this bug report as a general discussion and debate forum. I don't want to lock the thread, but it is pretty hard to separate out the noise at this point. Thanks!
Am I only one who tries to understand why the hell Steam needs to wipe
a directory on my machine? Even if it was Steam who brought it here,
why should it ever wipe it? Can't it do something not dumb instead?
@Plaque-fcc Like leaving unused files forever keeping your bits flipped in unnecessary ways? Whatever. We're not here to discuss engineering decisions, we're here to comment on a BUG (By definition, something that didn't work as intended).
@johnv-valve I believe this one-liner deeply interests many people, plus we're all worried about unpredicted and/or unpredictable edge-cases. I'm not inclined to believe any one-liner can avoid all edge cases, so it would be great if said "one line" was provided for scrutiny, and if more checks for the variables used with rm and folders to be erased were put in place.
I also disagree with you (And I hope you get what I mean) in that it's not a matter of "can reproduce", it's a matter of "can happen", especially if later someone changes the script in any unpredictable way. Redundancy can feel horrible, but rm -rf is one of those cases I'm pretty sure it's FAR better to be safe than sorry, especially if you files are on the line.
@frnco
...it's not a matter of "can reproduce", it's a matter of "can happen"...
Establishing "can reproduce" is critical to preventing "can happen" since if you can't reproduce the error then you can't know if you've fixed it or not.
@frnco the referenced one-liner is in the current steam linux beta client:
# Check before removing
if [ "$STEAMROOT" != "" ]; then
rm -rf "$STEAMROOT/"*
fi
@rpdelaney That's why I said "I hope you get what I mean".
Maybe it's even impossible to reproduce this issue on that file, especially after the one-liner, but if you look at just a block of code, it's easy to reproduce the "erasing of everything". We need at LEAST rm so let's test every line that includes rm.
rm -rf "$STEAMROOT/"*
This for instance is easy to debug and test. If you wanna, try writing unit tests for it (But please be careful of where you run it. :D).
Bugs that depend on state are easy to reproduce if you isolate the code and "guess" possible states. That's how we unit-test stuff isn't it? That's the kind of bugs that happen "only in production" or "only on your client's 6-year-old-pc with this and that specific software installed". Do you go to your clients to code on their computers whenever you find a bug...? Or do you just tell them you can't reproduce...?
Bash scripting, monolithic and confusing code... Complaining about needing to reproduce something under those coditions is not an argument, it is, at best, an excuse. The solution is easy: isolate the code, make it work properly whatever the "other lines" throw at it.
@Tele42 and @johnv-valve I would also worry about the risk of $STEAMROOT being /, *, ., .. etc (Symbols that have meanin on *NIX systems, basically) or a system folder (/opt, /home, /usr etc., obviously including User's home folder). Not that I would manually write checks for every possibility, I would first study on the matter to see which values could end up there, and how to best "sanitize" the variable, so to speak. i.e., if there's a flag to protect system folders, I would use it. If * only adds to the risk (Better Git Blame that to be sure it is not needed though, could be a fix for some other edge case), I would remove it. And so on.
The best fix seems to be checking the folder for some specific file(s), but that coupled with manual checks for $STEAMROOT and some flags to protect system files becomes pretty safe. It CAN go wrong, as everything on a computer (The nature of bugs), but at least the script "does its best" to avoid it, which I believe is what we all want: To feel the software we run tries to preserve us, our systems and our files.
@frnco
Do you go to your clients to code on their computers whenefer you find a bug...? Or do you just tell them you can't reproduce...?
I think that's what he's doing when he asks for help with reproducing the bug. I'm afraid I don't understand what you're getting at.
@rpdelaney I'm getting at "rm should be dealt with more care, especially if the script is too big and you can't unit-test it."
rm-rf /* is just a bit worse than rm -rf ./* or rm -rf ../* and so on.
It's a bit like protecting against race conditions: Never running on them is not enought reason to not try to protect against them. If there's a chance it could happen, as slim as it may be, you code in a way to prevent it. If you parse one file of 20b in one thread and another file of 200Mb on another thread, you don't just assume both files are finished after the 200Mb file finished, you check for both, even if it's a problem that won't surface under any normal circumstances.
Dealing with a bash script this big and confusing feels remarkably close to that. Feels like everything work, but an unchecked rm still erased a ton of files. Classic example where "better safe than sorry" could have prevented it with a handful of ifs. Ugly, perhaps, but safer. And since the script is already a mess, I don't see any reason not to add more and better checks, as many of the previous commenters.
Is it strictly necessary to do rm -rf "$STEAMROOT/"*?
Why not rm -rf "$STEAMROOT"; mkdir "$STEAMROOT"?
[[ -d "$STEAMROOT" ]] && {
rm -rf "$STEAMROOT"
mkdir "$STEAMROOT"
}
It will create a case where if "$STEAMROOT" is a symlink, we will remove it and put the new files in there. But:
And please consider hardcoding the path to "$HOME/.local/share/Steam":
if [[ "$XDG_DATA_HOME" ]]; then
STEAMROOT="$XDG_DATA_HOME/Steam"
else
STEAMROOT="$HOME/.local/share/Steam"
fi
Or just:
STEAMROOT="$HOME/.local/share/Steam"
@ftp: Having a symlink is necessary when %HOME is too small or if it would be insane to use the SSD for games.
As I said before, this argument should be included: --preserve-root.
@7eggert
Having a symlink is necessary when %HOME is too small or if it would be insane to use the SSD for games.
No. Use mount -o bind.
@johnv-valve you should just lock this thread. Obviously people haven't
picked up on the whole "not a general discussion forum".
On Thu, Jan 22, 2015 at 11:12 AM, Julian Ospald [email protected]
wrote:
Having a symlink is necessary when %HOME is too small or if it would be
insane to use the SSD for games.No. Use mount -o bind.
—
Reply to this email directly or view it on GitHub
https://github.com/ValveSoftware/steam-for-linux/issues/3671#issuecomment-71045646
.
mount -o bind requires root privileges. The point of using $HOME is not to require root privileges, otherwise you'd use /var/lib/Steam.
Besides, it's system specific.
@7eggert, you can also tell Steam where you want your games installed. It is entirely possible to set a custom SteamApps location in settings.
I'm sorry for contributing to the offtopic, it will be the last time I do this.
Q: How many developers take to fix a bug in a shell script?
A: 115 participants so far, still unfixed.
Lets move the discussion to the Steam for Linux group discussion post.
it is already fixed.
http://store.steampowered.com/news/15512/
...is there anyone in the world who uses Steam on a linux machine where they can't escalate to root to make necessary configuration changes?
@mwestphal : @johnv-valve stated the following:
We shipped a one-line fix to avoid the one situation where we could reproduce the problem. We are still working on some more comprehensive changes, but we wanted to get a fix out there quickly in case this somehow hit anybody else.
If anybody knows how to actually reproduce this bug, please post the steps here or email me directly. So far we have not been able toe reproduce it and I would hate to be barking up the wrong tree if the problem is really somewhere else.
Also, I'd appreciate it if people would not use this bug report as a general discussion and debate forum. I don't want to lock the thread, but it is pretty hard to separate out the noise at this point. Thanks!
This potentially only a partial fix; discussion has been moved to the Steam forums. There the community can discuss and review the "one-line fix" and see if any suggestions can be offered.
Solution: Just don’t delete user data. Ever.
Has this issue not been fixed yet? If it has been fixed, it should be closed. If it is not fixed, it needs more attention.
Yes, the issue that is tracked in this issue report was resolved.
kisak-valve said that this is resolved. It's not, the "fix" doesn't do anywhere near enough sanity checking for a script that has the potential to delete the user's files.
Here's what I consider to be the absolute minimum level of sanity checking required:
(This script was written by me and is hereby placed in the public domain, or the 2-clause BSD license if you are in a jurisdiction that does not acknowledge "public domain". Do whatever you want with it, no royalties or any form of compensation or acknowledgement is expected or required, even the BSD license requirement to include a copyright notice is waived. I renounce all rights to this trivial code)
$ cat /tmp/steamhome.sh
#!/bin/bash
# Example of a minimal fix for:
# https://github.com/valvesoftware/steam-for-linux/issues/3671
#
# Notes:
# 0. This script is public domain or, at your option, BSD-licensed.
# 1. The steam.sh script has 'STEAMROOT="$(cd $(dirname $0) && echo $PWD)"'
# WTF! that's crazy. assignment by side-effect (and hoping the `cd` doesn't fail),
# is just tempting Murphy, and whoever wrote it doesn't know bash's built-in `pwd`
# returns the current dir, as does `/bin/pwd` which has existed for decades.
# 2. in case it ever matters, FreeBSD's `stat` command is not the same as GNU's and has
# slightly different printf-style formatting options, and their `readlink` only has
# a `-f` option rather than `-e`, but that's adequate for this job.
STEAMDEBUG=1
dumpsteamvars() {
# if $STEAMDEBUG is 1 display all env vars with 'STEAM' in the name
[ "$STEAMDEBUG" == '1' ] && typeset -p | grep STEAM
}
error() {
# This function takes either 1 or 2 arguments, a message to print to stderr
# (required), optionally preceded by an exit code (defaults to 1 if missing)
local exitcode=1
[ -n "$2" ] && exitcode="$1" && shift
printf "FATAL: %s\n" "$1" >&2
dumpsteamvars
exit $exitcode
}
# SteamOS is Linux, so we can assume GNU coreutils, which includes basename,
# dirname, readlink, id, stat, etc.
# base name of the script, i.e. without the path.
STEAMCMD="$(basename "$0")"
[ -z "$STEAMCMD" ] && error 1 "STEAMCMD is empty"
# 'readlink -e' canonicalises the path/filename, resolving all symlinks
STEAMROOT="$(dirname "$(readlink -e "$0")")"
[ -z "$STEAMROOT" ] && error 2 "STEAMROOT is empty"
cd "$STEAMROOT"
STEAMUSER="$(id -u -n)" # login name of the user running steam
STEAMUID="$(id -u)" # numeric uid of that user
STEAMROOTUID="$(stat -c '%u' "$STEAMROOT")" # numeric uid of $STEAMROOT directory's owner.
STEAMROOTOWNER="$(id -u -n "$STEAMROOTUID")" # login name of $STEAMROOT directory's owner.
# now check for some problems that could lead to disaster and
# abort on anything even slightly dodgy.
[ -z "$STEAMUSER" ] && error 3 "STEAMUSER is empty"
[ -z "$STEAMUID" ] && error 4 "STEAMUID is empty"
[ -z "$STEAMROOTUID" ] && error 5 "STEAMROOTUID is empty"
[ "$STEAMUID" != "$STEAMROOTUID" ] && error 6 "$STEAMROOT owned by $STEAMROOTOWNER($STEAMROOTUID). STEAMROOT should be owned by $STEAMUSER($STEAMUID)"
[ ! -e "$STEAMROOT/$STEAMCMD" ] && error 7 "Something very odd is going on, can't find myself ($STEAMCMD is not in $STEAMROOT)"
# put more sanity checks here
echo "Everything seems to be OK"
dumpsteamvars
If I save this as /tmp/steamhome.sh and run it, I get:
$ /tmp/steamhome.sh
FATAL: /tmp owned by root(0). STEAMROOT should be owned by cas(1000)
declare -- STEAMCMD="steamhome.sh"
declare -- STEAMDEBUG="1"
declare -- STEAMROOT="/tmp"
declare -- STEAMROOTOWNER="root"
declare -- STEAMROOTUID="0"
declare -- STEAMUID="1000"
declare -- STEAMUSER="cas"
Exactly what it's supposed to do. If I copy it to ~/.steam/ and run it, I get:
$ cp /tmp/steamhome.sh ~/.steam/
$ ~/.steam/steamhome.sh
Everything seems to be OK
declare -- STEAMCMD="steamhome.sh"
declare -- STEAMDEBUG="1"
declare -- STEAMROOT="/home/cas/.steam"
declare -- STEAMROOTOWNER="cas"
declare -- STEAMROOTUID="1000"
declare -- STEAMUID="1000"
declare -- STEAMUSER="cas"
Again, exactly what it's supposed to do.
And, thanks to readlink -e, if ~/.steam/steamhome.sh is a symlink to e.g. /tmp/steamhome.sh:
$ ln -sf /tmp/steamhome.sh ~/.steam/
$ ~/.steam/steamhome.sh
FATAL: /tmp owned by root(0). STEAMROOT should be owned by cas(1000)
declare -- STEAMCMD="steamhome.sh"
declare -- STEAMDEBUG="1"
declare -- STEAMROOT="/tmp"
declare -- STEAMROOTOWNER="root"
declare -- STEAMROOTUID="0"
declare -- STEAMUID="1000"
declare -- STEAMUSER="cas"
You are always welcomed to use a containerized Steam (no performance impact) in case you afraid it can damage anything on your system, except the Steam-related files itself of course --
https://hub.docker.com/r/andrey01/steam/
Always put Steam in a 32 bit chroot in order to run it on a recent system (64 bits of course). Only game devs want 32 bit nowadays so a chroot is necessary anyways if you don't want to clutter your system with a shitload of multiarch stuff.
If you prevent steam from deleting all your data that's a bonus, too.
In fact containers and chroot are very secure, but isn't the best option from user's POV. An application which sane scripts which doesn't delete all your files still is the best option. May be one day when Flatpak and Snap become a standard we can rethink this.
@mhalano You have to consider that many devs on steam stop supporting Linux because they say "1% of our customers use Linux but they account for 50% of our support requests". In view of this steam should be distributed as a container to keep as much of the environment under control as possible.
Source?
An application which sane scripts which doesn't delete all your files still is the best option.
Yes, of course. But as long as the software needs 32 bit libs I'm not going to run it outside a chroot/container/whatever. I don't want to clutter my system with multiarch crap.
"1% of our customers use Linux but they account for 50% of our support requests"
No surprise. Most of players on Windows are kids, most of players on Linux are programmers. Also these are "bug reports" and not "support requests".
@mhalano You have to consider that many devs on steam stop supporting Linux because they say "1% of our customers use Linux but they account for 50% of our support requests". In view of this steam should be distributed as a container to keep as much of the environment under control as possible.
Yeah, it is really a big problem for content creators to have an engaged audience. /s
@ohjames, but it could. There isn't a lot of finality either way without more data. These users could be finding valid bugs, in which case they are doing the developers a service.
An engaged audience does not equate to a large number of support requests.
Bug reports aren't support requests.
So some random guy said "An engaged audience does not equate to a large number of support requests" twice but I have no idea why this truism is being repeatedly asserted?
no they didn't, and you're being neither funny nor clever.
@ohjames He's just treating you with your own medicine.
Using some random dev's made up percentage fud as a fact is no better than what Garry Newman does.
But I guess now that you deleted your comments people can't actually support any of this, right?
Right, cause deleting your comments is definitely going to end this convo (whether you're being harassed justly or wrongfully).
In any case, this is all off-topic, isn't that so?
@kisak-valve please can you lock this? It's getting really off-topic here.
@simi, the issue is closed, but not fixed as well as it should be. Locking it is going to keep the issue from being re-opened and actually resolved.
I'd rather not lock issue reports if I don't need to. At this point, I'd need either a test case that causes this issue or a request from a Steam dev to re-open this issue.
Since there is over a hundred participants on this issue report, I'd like to see at least 25 thumbs up on @simi's request to lock this issue.
If Valve properly fix the problem (is not that hard) the off-topic messages go away.
@kisak-valve, @craig-sanders has shown a fix here: https://github.com/ValveSoftware/steam-for-linux/issues/3671#issuecomment-328726591
@kisak-valve, @craig-sanders has shown a fix here: #3671 (comment)
Sorry, but none of you really understand the problem. The problem is not the lack of arbitrary sanity-checks, the problem is that recursive deletion is an inherently problematic operation, especially if it is non-interactive. That is also why no package manager out there will ever do rm -r in any way. You track the installed files and only ever remove known files, never directories and never recursive.
@kisak-valve issue was marked as closed (and by your comment also as resolved) and it is here just for annoying offtopic discussion. I don't see any reason to keep it unlocked and keep offtopic discussion. I would like to stay watching this issue, but I don't care about offtopic.
Once there will be news, you can:
and interested people will get notification.
I don't know if they enjoy the publicity and free labor or what but Valve will never fix problems like this, seriously there are many threads like it on github alone. Looking at steam.sh should make anyone cry in a corner.
There are lovely assumptions like this all over the place:
# Save the prompt in a temporary file because it can have newlines in it
tmpfile="$(mktemp || echo "/tmp/steam_message.txt")"
That is so wrong on so many levels but they've hardcoded things everywhere. I can only imagine what the Windows client is like.
This one just boggles my mind:
# Set up the link to the source code
ln -sf "$STEAM_RUNTIME/source" /tmp/source
else
echo $"STEAM_RUNTIME couldn't download and unpack $STEAM_RUNTIME_DEBUG_URL, falling back to $STEAM_RUNTIME"
Look around those lines and cry. The RUNTIME_DEBUG_URL is based on a grep with no error checking. Isn't even over SSL. Rather hilarious thing is they explicitly force http1.0 in download_archive anyway.
My point is there are so many places this bug can surface it's no wonder Valve are unable to fix it. I wouldn't personally go near a LAN with steam running.
Conclusion: They have absolutely no idea how to develop software for Linux-based operating systems.
Conclusion: They have absolutely no idea how to develop software for Linux-based operating systems
That is correct. And it's not even so much about the poor quality shell scripting. They don't use the opensource community to their benefit. They have no understanding of the ecosystem or the community.
There are lots of people out there that would rewrite their scripts for free and even collaborate on linux-specific steam code. Apart from the tons of suggestions here, there have also been numerous PRs about making the scripts POSIX compatible and whatnot. They have been ignored.
Linux is basically a platform where you get reviews, suggestions, code and even professional help for free. Except valve doesn't use it. That's not really a problem of "oh, I let my grandma write the bash scripts that handle safe user data removal", it's your huge ignorance of the specificities of a platform and its community. Something went wrong during your "linux agenda".
But it totally makes sense given the way Valve works internally. There was employee or a group that made the project, but now they are either not interested in it or not even employed anymore. Who will merge PRs, if nobody knows the code?
@hasufell yes, keeping track of all files and deleting only known files when uninstalling is what a package manager should do.
Steam doesn't do that, and likely never will. Steam isn't a real package manager. It's a game library manager originally written for an OS where package management is an alien concept, where each program is installed by running its own installer program (and assumes it's the only program that will ever run on the system so can do whatever TF it wants to without caring about screwing up other software the user may have installed)....For all its flaws, Steam on windows is actually a great leap forward compared to that even if it does seem primitive and broken compared to standard practice on linux or mac. Hell, even on Linux you still get idiot devs telling users to ignore the package manager and just run make install or the insanely insecure curl URL | bash.
Anyway, as always, it's more useful to deal with things as they are, not as they would be in an ideal world. Without the magic ability to make steam work like a real package manager, having a bunch of paranoid sanity checks in front of anything that affects file deletion is the most useful thing to do....equalled only by:
$" pointed out by @h1z1. That is not the only instance - there are 21 more in my copy of steam.sh as of today. $" is valid syntax in bash but I doubt very much that the script author's purpose was to do locale translation.$(). and failure to double-quote $().carefully examine every instance of rm -r in the script (7 according to grep -c) and make sure they're as safe as possible given the hackish nature of the script. Perhaps even write a safe_rm wrapper function that does some sanity checking (e.g. existence and ownership of dir), before doing a recursive deletion, and use that wherever rm -r is run.
the many newbie errors like:
#!/usr/bin/env bash. bash is always in /bin on a linux system, also on OS X. and using env to find a script interpreter is brain-damaged.ldd "$1" | grep X | grep -v Y | grep -v Z | awk '{print $1}'ldd "$1" | awk '/X/ && ! /Y|Z/ {print $1}'ldd "$1" | awk '/not found/ {print $1}'These mistakes and newbie errors are just what I've noticed from a casual glance at the script. There are undoubtedly many more.
bash is always in /bin on a linux system, also on OS X.
Many Linux distros store it in /usr/bin instead, along with everything else that usually goes in /bin.
Steam doesn't do that, and likely never will. Steam isn't a real package manager.
You missed the point. It isn't actually that hard for a program to keep track of all the files it will output in a given directory. Even programs on windows are able to do that sort of thing. No one said steam should become a package manager. It should just be able to clean up after itself and while it is updating.
@aaronfranke really? name these "many distros". in fact, name one. bash has been in /bin on linux forever because that's where system-native shells belong. third-party shells tend to go in /usr/local/bin. or in some bizarre location like /usr/opt/local/where/the/fuck/is/it on solaris.
@hasufell no, i didn't miss your point. you missed mine, which is that wasting time complaining about the fact that steam isn't a real package manager and doesn't behave like one is completely pointless and useless. Deal with things as they are, not as they should be and not as you wish they were. Steam is what it is, and there's a limit to what and how much can be fixed or improved.
which is that wasting time complaining about the fact that steam isn't a real package manager and doesn't behave like one is completely pointless and useless.
No, that's not what I said. Package managers are orthogonal to the point I made, which suggests you actually didn't understand the point.
Deal with things as they are, not as they should be and not as you wish they were. Steam is what it is, and there's a limit to what and how much can be fixed or improved.
That is just wild guessing. Why would it not be possible to fix the behavior as explained? I don't see any technical limit there. Please explain what "limit" that would be.
you may think you were making some significant point, but really you were just wishing that steam was a real package manager. It isn't, and no amount of bitching about it is ever going to get Valve to devote the time and resources to make it one. There's little or no benefit to them in doing so - steam mostly functions well enough at what it is, a games library manager.
as for your "wild guessing" comment and request for an explanation of the limit - we're talking here about the steam.sh shell script, which is a wrapper around the steam application, doing environment setup and other things (like helpfully deleting all user files on certain error conditions). Rewriting the steam app so that it acts like a package manager should is way beyond the scope of fixing the obvious errors in a shell script. I would have thought that was obvious.
In case you hadn't noticed, Valve don't even acknowledge the fact that their crappy steam.sh script is still broken and puts user files at risk - there's some small hope that they might eventually do that and adopt some of the ideas and suggestions in this thread (there's some evidence they've already done that for some things), but there's no way they'll ever re-write the steam app to incorporate the basic features of a package manager.
you may think you were making some significant point, but really you were just wishing that steam was a real package manager
Again, no.
as for your "wild guessing" comment and request for an explanation of the limit - we're talking here about the steam.sh shell script
No, we are talking about steam as a whole.
Rewriting the steam app so that it acts like a package manager should is way beyond the scope of fixing the obvious errors in a shell script. I would have thought that was obvious.
Again, no. This is not about package managers. You seem to have no understanding of how the proposed technology works.
This is not about fixing half-assed shell scripts, which are already by concept wrong. This is about correctness, which is crucial when you deal with user files. Recursive deletion is never correct from an automated cleanup POV. Recursive deletion is something a user may trigger, based on his needs.
but there's no way they'll ever re-write the steam app
First, there is no rewriting of the "steam app" involved. Second, that's guessing again.
@craig-sanders
https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/
Solaris started it, Fedora was one of the first Linux distros to do it.
@aaronfranke really? name these "many distros". in fact, name one. bash has been in /bin on linux forever because that's where system-native shells belong. third-party shells tend to go in /usr/local/bin. or in some bizarre location like /usr/opt/local/where/the/fuck/is/it on solaris.
@craig-sanders: Sorry to barge in, but maybe you have to update your knowledge on this one:
/usr/bin/bash (https://koji.fedoraproject.org/koji/rpminfo?rpmID=11161824)usr/bin/bash (https://www.archlinux.org/packages/core/x86_64/bash/)And probably others already, as this merge of /bin to /usr/bin was advocated by systemd, so probably many other distros that switched to systemd will eventually follow.
No big deal since the merge to /usr/bin is done slowly and places symlinks for maintaining backwards compatibility.

So using /bin/bash is safe on “traditional” systems as well as on nowadays systems.
Guys, we are bike shedding solving a problem which has already had a suitable solution presented and alternatives. Discussing it ad nauseam isnt going to make Valve come out and fix it if they have no interest, we have suitably voiced opinion here. Lets post a link to some other forum (Reddit, Google groups, or elsewhere) and take the sidebar discussion there.
No big deal since the merge to /usr/bin is done slowly and places symlinks for maintaining backwards compatibility.
So using /bin/bash is safe on “traditional” systems as well as on nowadays systems.
This may be true so far, but every backwards compatibility will eventually be going away.
And this:
#!/usr/bin/env bash. bash is always in /bin on a linux system, also on OS X. and using env to find a script interpreter is brain-damaged.
is certainly outdated advice for any software maintained currently or in the future. Distributions will have to do enough patching for legacy software once such backwards compatibility is faded out.
@ju2wheels But a Half Life 3 talk didn't even have a chance to start!
Has this problem been fixed? I really want to play the metro series, but this scares the crap out of me.
@user15177 Set up a chroot for Steam and run it from there so it can do no harm to your actual system.
@craig-sanders Since you posted some cleaned-up code from the script and some good Bash scripting advice, a note: Always use the [[ ]] test syntax in Bash-specific scripts. It's safer and cleaner in all cases.
Is this fixed? xD
whoa what the heck does the unassigned message mean
@aviwad It's just something GitHub does automatically when the assigned person doesn't actually do anything about the issue and someone comments on it again.
Its still happening. It deleted almost everything on my Ubuntu.
Hello @nicklleite, the investigation of the issue in this issue report concluded several years ago. Please open a new issue report.
S̻̱̳͓̜͓̱̮̣̿ͪ̇ͦ̐͌ͣ͗͆ͬ̋͌͒̕͞Y̧͎͕̭̘̺̳̮̦͉̭̝̦̒ͩ̔͢͡Š̶̵̘̬̦͔̖̜͈̭̞̫̣̹̻͈̖͍̗͎̜͚̞̣͇̺͇̣̰̬͕̫̜͚͉̭͎͍̱̲̟̼͕̟̥̲͖̦̪͚̜̮͖̥̮̻͔̝̺̪̲̱ͥ̊ͮͤͯͮͥ͟͞T̠͈̻̰̦̲͉̺̱͔̗̮̜̰̘͚̺̩̝̠̖̏ͫ̌͢͟ͅE̯͕͇̱̩͓̣̬͍̹̘̜͈̦̜̲̣̹̬͚̪͎͎̲̮̫̪̲̠͇̭̼̹̝̞͕͚̝̥͉͈̪͔̯̺͚̖̺̳̭̹͖̠̬̮̻͉͍ͧ̃ͫ͗̽̒ͪ̑ͬ͋ͭ͘҉̶͜͝M̶̮̹̦̝̠̥̞͎͓̳̬͈͉͍̞̬̲͙̳̰̮̞̝̱͔͖̰̲͔͇̣̲̩̥̱̲͓̩̫̬͇̜̞̰̥̲̖͆ͣ͛̈̀͘͝ͅͅ ̨͚̻͙̼̞̰̱̯͔͕̟͚̗̤̹̮͇̠̙̣͔̤̝̭͔͓͓̠̱͎͔̯̰̖͙̣̰͍͕͉͙̐̒̽ͤ̂͊ͣͅͅͅǏ̙̼̤͕̲͖̻̯̥̻̣̪̙̠̹̻̮͇̭͍̤̘̣̺͖͎̻͓̰̬͙̝̻͓̇̊̋̇̑ͨ͊̋̉͗͋ͭͥ͗ͦ̐ͣͧͅͅ͏S̷̸̵̴͇̦̲̩̠̠̝͔̘̺̥̖̑̑̐͑̈́ͧͫͨ̌̈̏͠ ̷̺͇̪̩̖͕̻̤̜͉̙̞̬̪̞̞̤̖̺̼̩̟͖͈͕̩̫͖̯͓͇̙̲̗̬̳͙̗͍̗̂ͤ̃̽̎̐͐ͩ͢D̝̗̭̖̫͉͙͓̹̻͖̝̩͋͊͐͋͛̆͟͜ͅͅO̷̷̹̼̟̥͎̤͎̺̮͉̯̗̬̫̟̘͕̼̗̬̦̟͉̝̲̫̪̤̮͙͕̻̐͋ͫ͊̔͑ͥ̅͘͞ͅͅW̢͓̠̹͎͈͙̞̣̬̙͔̖̦̳͕̞̙̬̰̪̪͔̖̻̭͇̻͔̙͍͖̊͛͋̉̓̏ͥ̍̌͌̎͜ͅͅͅN̴̷̡̺̱͔̖̠̱͔̩̠̳̙̜͎͉̗̮̽̔ͫ́̔̑̅́̊̐ͮͧ́̇͝ͅ
?
Edit: Please stop posting stupid image memes or unhelpful messages. This interferes with Valve's ability to sift through the noise and see if anyone can figure out what triggers it.
This may not be a common problem because I change all sorts of configuration about my system. The script in question does something in a really, really stupid way, but it probably doesn't trigger the fail scenario for every system because...
Original Bug:
I am not sure what happened. I moved the folder in the title to a drive mounted under /media/user/BLAH and symlinked /home/user/.local/steam to the new location.
I launched steam. It did not launch, it offered to let me browse, and still could not find it when I pointed to the new location. Steam crashed. I restarted it.
It re-installed itself and everything looked great. Until I looked and saw that steam had apparently deleted everything owned by my user recursively from the root directory. Including my 3tb external drive I back everything up to that was mounted under /media.
Everything important, for the most part, was in the cloud. It is a huge hassle, but it is not a disaster. If there is the chance that moving your steam folder can result in recursively deleting everything in the directory tree you should probably just throw up an error instead of trying to point to other stuff. Or you know, allow the user to pick an install directory initially like on windows.
My system is ubuntu 14.04, and the drive I moved it to was ntfs if its worth anything.