Git Product home page Git Product logo

Comments (13)

BurntSushi avatar BurntSushi commented on August 20, 2024 1

It's not quite that simple. It's pretty typical for tools to change their behavior based on whether they believe stdin is readable or not. Whether stdin is attached to a tty or not is just one part of that calculation.

Here's the logic that ripgrep uses as an example: https://docs.rs/grep-cli/0.1.6/src/grep_cli/lib.rs.html#190-213

Logically speaking: read from stdin if it's believed to be readable, where "believed to be readable" means "it's not a tty and has a file type amenable for reading."

from atty.

BurntSushi avatar BurntSushi commented on August 20, 2024 1

The problem is that your cron implementation is attaching a tty to stdin for some reason, based on what you told us. There is really nothing more to be done here because that is the problem. It's not a problem with this crate.

You're only choice from what I can tell is to either add a flag that forcefully prevents reading from stdin, or somehow modify your heuristic for detecting whether stdin might be readable or not. You haven't really given us much to go on here, other than the fact that your cron daemon is advertising a tty on stdin for subprocesses it executes. (I find that highly unusual. You might consider looking into that issue more deeply, and possibly asking the maintainers why it's happening. Just make sure to provide a minimal reproducible example using libc apis directly.) Otherwise, you could probe at the stdin file descriptor a bit more. For example, what is its file type?

from atty.

neithernut avatar neithernut commented on August 20, 2024

What cron-daemon are you using? (And what version?)

from atty.

nbari avatar nbari commented on August 20, 2024

I am using the cron that comes by default in the latest FreeBSD 13 (amd64): https://www.freebsd.org/cgi/man.cgi?cron(8)

from atty.

neithernut avatar neithernut commented on August 20, 2024

First of all: isatty doesn't actually tell you whether your process does or can receive input via stdin but whether stdin is connected to a tty. There is no way that I'm aware of that a process can detect whether it may receive any input from stdin (if it is open).

Assuming you do want to know whether the process was spawned from a terminal and not by your cron: isn't your logic backwards?

let input_stdin = !atty::is(atty::Stream::Stdin); // isatty returns false if there's something in stdin.
if input_stdin {
    println!("stdin"); // how to prevent this to happen when calling it from a cron
}

atty::is returns true if stdin is connected to a tty, which should not be the case for a cronjob, so we'd expect input_stdin to be true when run as a cron-job. Or does your program actually expect input only when it is not run from a terminal?

from atty.

nbari avatar nbari commented on August 20, 2024

It has been working "fine" (https://github.com/s3m/s3m/blob/master/src/s3m/options.rs#L211) but I never tested within a cron.

atty::is returns true if stdin is connected to a tty

I have been using it to detect if something is in the stdin so that I can read the input and stream it, but maybe is not the way I should be doing this.

from atty.

neithernut avatar neithernut commented on August 20, 2024

I have been using it to detect if something is in the stdin so that I can read the input and stream it, but maybe is not the way I should be doing this.

Yes, that's indeed not how you do this. Tools typically just read until the "end of file" in such situations.

from atty.

nbari avatar nbari commented on August 20, 2024

I will give it a try, thanks for sharing 👍

from atty.

nbari avatar nbari commented on August 20, 2024

From a cron, I still getting like if there is something to read from stdin,

wondering what could be the cons of using something like this:

let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
if line.len() > 0 {
// read from stding
}

from atty.

neithernut avatar neithernut commented on August 20, 2024

You don't use a read just for checking for input, there's no point in that. It only complicates your code, since you end up with that extra line you have to incorporate. You just read and handle the result, which you have to do anyway in one way or another. For example, if you really only expected one line, you'd do something like this:

let mut line = String::new();
if std::io::stdin().read_line(&mut line).unwrap() > 0 { // read_line will return Ok(0) at EOF
    // use line
}

Of course, you'll probably want to handle read errors properly instead of just calling Result::unwrap (even if you ultimately still just bail out, but with a more user-friendly error message).

If your input is line-oriented, you can just use the iterator returned by BufRead::lines. Consuming such an iterator (through a for loop, Iterator::try_for_each or similar) will usually give you the behaviour you want.

Still, using the heuristics like the ones linked to by @BurntSushi before the first read does make sense if you want your program to be robust. These heuristics aim at ensuring stdin is "what you expect" and not something "weird" which may exhibit some unexpected behavior. If the check fails, you probably don't want to read from stdin at all but just pretend that it's already at EOF.

Though I have to admit I myself usually don't include such checks in my programs. Or at least I didn't do so in the past.

from atty.

nbari avatar nbari commented on August 20, 2024

The problem I am trying to solve is to prevent reading from stdin when launching my app from a cron when indeed there is nothing in stdin.

my app is a simple s3 uploader that can read from stdin (stream) or just pass the file from the command line (multipart upload):

s3m /path/to/file aws/bucket/file

or pipe something stdin :

 mariabackup --stream=xbstream | s3m aws/bucket/file 

But I notice what when running the app from a cron atty returns that there is something to read from stdin and I end trying to read from stdin but since there is no input 0 I end ignoring the arguments (this because of the logic of the application, in where I give preference to stdin, maybe the easy way is just to add a flat to read from stdin)

Because of this (since I may have some input) if the read length > 0 I could start streaming it, probably there is a way to prevent reading all the time, and find if there is something in stdin (covering cases like when running within a cron) this is what I am trying to figure out, so if have any ideas, hints, please let me know, I would appreciate it

from atty.

nbari avatar nbari commented on August 20, 2024

I will search more about it, how could I test the file type?

from atty.

BurntSushi avatar BurntSushi commented on August 20, 2024

https://doc.rust-lang.org/stable/std/fs/struct.FileType.html

Note also the FileTypeExt trait on Unix.

from atty.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.