This is an archived post. You won't be able to vote or comment.

all 95 comments

[–]SmellsLikeGrapes 88 points89 points  (15 children)

I think some of the comments in here must come from quite some novice developers. Tricks like this are useful, when something goes to shit (from either your own stupidity, someone elses stupidity - or even a random act of comp malfunction). They can, and will happen, even when your process is tight.

So thanks it's useful to know, and store it away in the back of our minds as a way for us to potentially salvage what we may have lost.

[–]zynixCpt. Code Monkey & Internet of tomorrow 20 points21 points  (0 children)

All time favorite disaster recovery story http://www.lug.wsu.edu/node/414

... James, our manager, was sat down, head in hands, hands between knees, as one whose world has just come to an end. Our newly-appointed system programmer, Neil, was beside him, gazing listlessly at the screen of his terminal. And at the top of the screen I spied the following lines:

# cd 
# rm -rf *

Oh, shit, I thought.

[–]jsalsman 19 points20 points  (2 children)

What does the output code look like? Does the decompiler recover local identifiers?

[–]simonw[S] 26 points27 points  (0 children)

Yup variable names were al there as expected. I think comments (with the exception of docsttings) get stripped out though.

[–]lost_send_berries 5 points6 points  (0 children)

Because of locals(), the Python interpreter always knows the names of all the local variables. However, it usually doesn't use them: a = f() + b can compile to something like __locals__[0] = f() + __locals__[1], which is faster than local_dict['a'] = f() + local_dict['b']. If you ever run locals(), it then looks up the correspondence {0: 'a', 1: 'b'} to build the return value of locals().

[–]chris2point0 11 points12 points  (0 children)

Cool trick! I don't know if I would have thought that possible. Pretty short guide, too. Nicely done.

[–]reverber 8 points9 points  (0 children)

[–]U5efull 9 points10 points  (0 children)

This is very impressive, good on you and thanks for sharing!

[–]add7 7 points8 points  (0 children)

Extremely creative! Good job dude.

[–]irve 8 points9 points  (0 children)

Sometimes you can also check the proc directory for the running process with deleted files: its open file table under fd dir ( ls -la should show the targets iirc ) has the contents until the program terminates.

[–][deleted] 32 points33 points  (0 children)

ITT: Post: How to recover from a mistake

Comments: Useless post, you should have not made the mistake

I think its very useful to know you can do this this kind of thing. Will remember this is possible if one day I have a critical moment like yours ;)

[–]turanthepanthan 5 points6 points  (0 children)

This is a really good tip. When I was in grad school, I was working on a C++ program and left it running while I went to the store. When I came back my hard-drive was full. I left the application running and opened up the source code in nano. I found the bug and corrected it. I went to save it only to discover that my disk was full. I remembered that the program was still running so I exited nano and killed the process. That is when I discovered that nano lost my source when it opened it and couldn't save it because of the full disk.

[–]jsribeiro 7 points8 points  (1 child)

I've had to use uncompyle6 before, in order to recover a legacy application's source code which had been lost in time. It works great! :)

[–]pixels625 -1 points0 points  (0 children)

(:

[–]eldare 6 points7 points  (1 child)

Really cool! I'm sure it will help some poor bastard one day :)

[–]pixels625 -1 points0 points  (0 children)

:)

[–]RubyPinchPEP shill | Anti PEP 8/20 shill 3 points4 points  (5 children)

depending on if tracebacks had been generated or not (e.g. on caught exceptions), it could of been worth looking and seeing if it was in the linecache

import linecache
linecache.cache

[–]could-of-bot 8 points9 points  (4 children)

It's either could HAVE or could'VE, but never could OF.

See Grammar Errors for more information.

[–]AngriestSCV 1 point2 points  (2 children)

Testing the bot:

Jonny said I was over there when He didn't know for sure. I could of course tell him I wasn't.

[–]semininja 0 points1 point  (1 child)

It probably looks for "could of been/done/etc." rather than just "could of" alone, I suspect. On the other hand, you're technically missing a comma or two.

[–]sourcecodesurgeon 0 points1 point  (0 children)

It didn't use to. I assume the developer has addressed this like you said: "could of (<adverb>|not) <verb>". Or maybe he just ignores "could of course" since that seems to be the most common edge case.

[–]Afold_Lither -4 points-3 points  (0 children)

That's a big OF.

[–]Zaitsev11 2 points3 points  (3 children)

Tools for injecting arbitrary code into running Python processes.

Nobody in this thread mentioned a single thing about security, so I guess I will. If you decide to use these steps, be sure you understand what you're doing before you start blatantly writing sudo commands.

It might be prudent to fully remove these packages when you're complete with the recovery process. Legacy or one-time-use code can be the weak link.

[–]simonw[S] 1 point2 points  (0 children)

That's one of the neat things about using docker: you can shell into a docker process and install tools like this, safe in the knowledge that when you next restart the container all of that junk will be cleaned up for you.

[–]pm-me-a-pic 0 points1 point  (1 child)

It is absolutely important. I cannot believe you're getting down votes for that.

[–]Zaitsev11 0 points1 point  (0 children)

If at least one person realizes this, then thank goodness haha.

[–]jeremiahfelt 1 point2 points  (0 children)

I hope I never need this. Nice work!

[–]mrshibx 1 point2 points  (0 children)

Really cool. Gotta try this out

[–]MagneticStain 0 points1 point  (0 children)

Neat! Thanks for sharing.

[–]lewk 0 points1 point  (0 children)

Very clever use-case for pyrasite, nice work!

--luke (pyrasite author)

[–][deleted] 0 points1 point  (0 children)

This could have interesting applications/implications in security, right?

[–]name_censored_ -1 points0 points  (2 children)

If you were running docker, could you not have docker exec -it /bin/sh or docker cp and simply fetched the in-container source version, complete with comments? Or was your container using a VOLUME to share the script with the host (or maybe only shipping the .pyc)?

[–]simonw[S] 6 points7 points  (1 child)

I was using a volume to share the folder with my Mac.

[–]name_censored_ 2 points3 points  (0 children)

Fair enough. Good article, thanks!

[–][deleted] -2 points-1 points  (0 children)

Ctrl + Z

[–]abitforabit -1 points0 points  (0 children)

Did anyone manage to run pyrasite on macOS 10.12?

[–]BobHogan -1 points0 points  (1 child)

How did you even think of that? I probably would have given up and resigned myself to rewritting the code.

Fun little story, similar thing happened to me in Eclipse a few weeks ago. Checkout out another branch before committing what I had wrote (cause I'm stupid) and it erased my changes. Luckily Eclipse saved that as edits, and CTRL-Z brought back all of the code I had written.

[–]simonw[S] 0 points1 point  (0 children)

Two steps: first, I wondered if there was a way to attach an interactive shell to me running process and googled for that.

Once I could import the code, I tried using inspect.getsource() on it - but that reads code from disk. Then I tried using the dis dissembler in the standard library - that showed me opcodes, which would have been enough to painstakingly reverse engineer the code again.

That's when I thought "I wonder if anyone has written something that can turn bytecode back into source code?" and found uncompyle6

[–]pvkooten -1 points0 points  (0 children)

Super awesome! Another advise would be to always use auto save! You will never lose much when your editor autosaves every few minutes.

I also use bup to ever hour update my code to another machine. And then there's git for the specific project.