Currently, --ask always results in a prompt being displayed, regardless of whether stdout is attached to a terminal or not. This leads to clumsy behaviour if inadvertently piped. Also, I have seen some people put --ask in EMERGE_DEFAULT_OPTS, which would break cron jobs. At least one package in the tree provides a cron job that calls upon emerge. I think it would be kinder to change the behaviour of --ask such that os.iastty(1) is called and, if false, emerge either raises an error or behaves as if the parameter were not specified at all. The latter approach would allow people to have their cake and eat it with respect to EMERGE_DEFAULT_OPTS.
Currently, it only checks if stdin is a tty: https://gitweb.gentoo.org/proj/portage.git/tree/pym/_emerge/actions.py?id=fcb77fe28505e98d281240e524d7073769809157#n2902 I guess we could make it check both, though it will break tee usage such this: emerge -a foo | tee emerge.out I doubt many people do that anyway, if any.
Hmm, yeah, it would break tee. This generated a small discussion on freenode and some other possibilities that emerged from that were: * have distinct make.conf variables for tty vs non-tty situations * ensure that packaged scripts that call upon emerge specify --ask n * filter out options from EMERGE_DEFAULT_OPTS that depend on user interaction * have a generic parameter to ensure non-interactive usage My main concern is where you have something like porticron, which is scheduled and calls upon emerge --sync. Currently, it won't actually sync if EMERGE_DEFAULT_OPTS contains "--ask". I think that it would be nice if a user could have it without the porticron author, in this case, having to care and update the script to negate whatever whichever features portage has. I can't think of a perfect solution, though.
correction: "... whichever interactive features portage has."
I'm not a Python man but this might serve to implement a compromise: def hasctty(): try: open("/dev/tty", "r+") return True except: return False That will yield True when going through a pipe, but shouldn't when run from cron.
(In reply to Kerin Millar from comment #2) > Hmm, yeah, it would break tee. This generated a small discussion on freenode > and some other possibilities that emerged from that were: > > * have distinct make.conf variables for tty vs non-tty situations > * ensure that packaged scripts that call upon emerge specify --ask n > * filter out options from EMERGE_DEFAULT_OPTS that depend on user interaction > * have a generic parameter to ensure non-interactive usage > > My main concern is where you have something like porticron, which is > scheduled and calls upon emerge --sync. Currently, it won't actually sync if > EMERGE_DEFAULT_OPTS contains "--ask". I think that it would be nice if a > user could have it without the porticron author, in this case, having to > care and update the script to negate whatever whichever features portage > has. I can't think of a perfect solution, though. To sync from a cron without the need for checking for the --ask parameter, then with >=portage-2.2.16 you can do emaint sync --auto The emaint system does not look at EMERGE_DEFAULT_OPTS. The sync system is now based in emaint. Emerge --sync just calls the new sync system in emaint with the --auto parameter so that it syncs only repos with auto-sync=yes set.
(In reply to Brian Dolbec from comment #5) > The emaint system does not look at EMERGE_DEFAULT_OPTS. The sync system is > now based in emaint. Emerge --sync just calls the new sync system in emaint > with the --auto parameter so that it syncs only repos with auto-sync=yes set. Interesting. Thanks for the tip.
Bump. Zac, any thoughts as to the method of checking for a controlling tty, per comment #4? It addresses the issue that originally motivated me to file this bug, without affecting pipeline usage. That is, under cron, the sample function will always return False.
(In reply to Kerin Millar from comment #7) > Bump. Zac, any thoughts as to the method of checking for a controlling tty, > per comment #4? I haven't found a case where it will return True. I just tried this in my shell: $ python -c 'open("/dev/tty", "r+")' Traceback (most recent call last): File "<string>", line 1, in <module> io.UnsupportedOperation: File or stream is not seekable.
Oops, I only tested under 2.7 originally. Fortunately, os.open can be used instead, as shown below. I have tested this method with success in both python 2.7 and 3.5. While not shown here, I also tested by way of a cron job. Incidentally, I use "state" in my equivalent perl code to enclose the result and avoid further open calls in the event that the function is called repeatedly. I haven't attempted that here, as I don't know how to do it properly in python. build ~ # cat hasctty #!/usr/bin/env python import os def hasctty(): try: os.open('/dev/tty', os.O_RDWR | os.O_NOCTTY) return True except: return False if hasctty(): print("true") else: print("false") build ~ # ./hasctty true build ~ # ./hasctty | cat true build ~ # ssh -T localhost '/root/hasctty' # no pseudo-tty false build ~ # ssh -t localhost '/root/hasctty' # force psuedo-tty true Connection to localhost closed.
I've (In reply to Kerin Millar from comment #9) > def hasctty(): > try: > os.open('/dev/tty', os.O_RDWR | os.O_NOCTTY) > return True > except: > return False That works for me. In addition to that, I suppose we should keep sys.stdout.isatty() check, since hasctty() returns True for a command run via nohup with /dev/null as stdin.
(In reply to Zac Medico from comment #10) > That works for me. In addition to that, I suppose we should keep > sys.stdout.isatty() check, since hasctty() returns True for a command run > via nohup with /dev/null as stdin. Err, I mean sys.stdin.isatty().
(In reply to Zac Medico from comment #11) > Err, I mean sys.stdin.isatty(). Indeed, checking stdin remains an important metric for determining whether interaction is possible.