adb 쉘에서 바이너리 stdout 데이터를 읽으시겠습니까?
adb 쉘 명령에서 바이너리 표준 출력을 읽을 수 있습니까? 예를 들어 screencap을 사용하는 방법의 모든 예에는 두 단계가 포함됩니다.
adb shell screencap -p /sdcard/foo.png
adb pull /sdcard/foo.png
그러나 서비스는 stdout에 쓰기를 지원합니다. 예를 들어 다음을 수행 할 수 있습니다.
adb shell "screencap -p > /sdcard/foo2.png"
adb pull /sdcard/foo2.png
그리고 이것은 똑같이 잘 작동합니다. 그러나 ADB에서 출력을 읽는 것은 어떻습니까? 내가 원하는 것은 다음과 같습니다.
adb shell screencap -p > foo3.png
그리고 SD 카드에 대한 중간 쓰기를 피하십시오. 이렇게 하면 PNG 파일처럼 보이고 (실행 strings foo3.png
하면 IHDR, IEND 등으로 무언가가 생성됨) 거의 동일한 크기가 생성되지만 이미지 리더와 관련하여 파일이 손상됩니다.
나는 또한 자바에서 ddmlib를 사용하여 이것을 시도했으며 결과는 동일합니다. 필요한 모든 라이브러리를 기꺼이 사용하겠습니다. 내 목표는 캡처하는 데 걸리는 총 시간을 줄이는 것입니다. 내 장치에서 두 명령 솔루션을 사용하면 이미지를 가져 오는 데 약 3 초가 걸립니다. ddmlib를 사용하고 stdout을 캡처하는 데 900ms 미만이 걸리지 만 작동하지 않습니다!
이것이 가능합니까?
편집 : 여기에 두 파일의 hexdump가 있습니다. 첫 번째 screen.png는 stdout에서 왔으며 손상되었습니다. 두 번째 xscreen은 두 가지 명령 솔루션에서 제공되며 작동합니다. 이미지는 시각적으로 동일해야합니다.
$ hexdump -C screen.png | head
00000000 89 50 4e 47 0d 0d 0a 1a 0d 0a 00 00 00 0d 49 48 |.PNG..........IH|
00000010 44 52 00 00 02 d0 00 00 05 00 08 06 00 00 00 6e |DR.............n|
00000020 ce 65 3d 00 00 00 04 73 42 49 54 08 08 08 08 7c |.e=....sBIT....||
00000030 08 64 88 00 00 20 00 49 44 41 54 78 9c ec bd 79 |.d... .IDATx...y|
00000040 9c 1d 55 9d f7 ff 3e 55 75 f7 de b7 74 77 d2 d9 |..U...>Uu...tw..|
00000050 bb b3 27 10 48 42 16 c0 20 01 86 5d 14 04 11 dc |..'.HB.. ..]....|
00000060 78 44 9d c7 d1 d1 11 78 70 7e 23 33 8e 1b 38 33 |xD.....xp~#3..83|
00000070 ea 2c 8c 8e 0d 0a 08 a8 23 2a 0e 10 82 ac c1 40 |.,......#*.....@|
00000080 12 02 81 24 64 ef ec 5b ef fb 5d 6b 3b bf 3f ea |...$d..[..]k;.?.|
00000090 de db dd 49 27 e9 ee 74 77 3a e3 79 bf 5e 37 e7 |...I'..tw:.y.^7.|
$ hexdump -C xscreen.png | head
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 02 d0 00 00 05 00 08 06 00 00 00 6e ce 65 |.............n.e|
00000020 3d 00 00 00 04 73 42 49 54 08 08 08 08 7c 08 64 |=....sBIT....|.d|
00000030 88 00 00 20 00 49 44 41 54 78 9c ec 9d 77 98 1c |... .IDATx...w..|
00000040 c5 99 ff 3f d5 dd 93 37 27 69 57 5a e5 55 4e 08 |...?...7'iWZ.UN.|
00000050 24 a1 00 58 18 04 26 08 8c 01 83 31 38 c0 19 9f |$..X..&....18...|
00000060 ef 7c c6 3e 1f 70 f8 7e 67 ee 71 e2 b0 ef ce f6 |.|.>.p.~g.q.....|
00000070 f9 ec 73 04 1b 1c 31 60 23 84 30 22 88 a0 40 10 |..s...1`#.0"..@.|
00000080 08 65 69 95 d3 4a 9b c3 c4 4e f5 fb a3 67 66 77 |.ei..J...N...gfw|
00000090 a5 95 b4 bb da a4 73 7d 9e 67 55 f3 ed 50 5d dd |......s}.gU..P].|
얼핏 보면 두 개의 추가 0x0d (13) 바이트가 추가 된 것 같습니다. 캐리지 리턴 ?? 벨이 울리나요? 빈 줄에 섞여 있습니까?
오래된 질문에 대한 답변을 게시하게되어 죄송합니다.하지만이 문제를 직접 발견했고 쉘을 통해서만 해결하고 싶었습니다. 이것은 나를 위해 잘 작동했습니다.
adb shell screencap -p | sed 's/^M$//' > screenshot.png
그건 ^M
내가 Ctrl + V를 눌러있어 문자입니다 -> Ctrl + m를, 그냥 작업 할 때 복사 붙여 넣기하지 않습니다 나타났습니다.
adb shell screencap -p | sed 's/\r$//' > screenshot.png
나에게도 트릭을했다.
달리 명령을 사용하지 않는 바이너리 출력을 미치게. 그래서 당신은 할 수 있습니다adb shell
adb exec-out
pty
adb exec-out screencap -p > test.png
https://android.googlesource.com/platform/system/core/+/5d9d434efadf1c535c7fea634d5306e18c68ef1f
STDERR에서 출력을 생성하는 명령에이 기술을 사용하는 경우로 리디렉션해야합니다 /dev/null
. 그렇지 않으면 adb
STDOUT에 STDERR이 포함되어 출력이 손상됩니다. 예를 들어, 디렉토리를 백업하고 압축하려는 경우 :
adb exec-out "tar -zcf - /system 2>/dev/null" > system.tar.gz
언급했듯이 "adb shell"은 캐리지 리턴 + 줄 바꿈 (0x0d 0x0a) 변환으로 줄 바꿈 (0x0a)을 수행합니다. 이것은 pseudo-tty 라인 규율에 의해 수행됩니다. 쉘에 사용할 수있는 "stty"명령이 없기 때문에 터미널 설정을 엉망으로 만드는 쉬운 방법이 없습니다.
그것은의 수 는 ddmlib으로 원하는 일을 할 수 있습니다. 장치에서 명령을 실행하고 출력을 캡처하여 유선으로 전송하는 코드를 작성해야합니다. 이것은 DDMS가 특정 기능에 대해 수행하는 작업입니다. 이것은 그 가치보다 더 많은 문제가 될 수 있습니다.
repair()
모든 CRLF를 LF로 변환 하는 솔루션은 흔들리는 느낌이 들지만 "손상된"LF에서 CRLF 로의 변환이 결정적이기 때문에 실제로 신뢰할 수 있습니다. 실수로 ASCII 모드 FTP 전송을 복구하기 위해 동일한 작업을 수행했습니다.
PNG 파일 형식은이 (및 관련) 문제를 정확히 포착하도록 명시 적으로 설계되었다는 점에 주목할 가치가 있습니다. 매직 넘버는 0x89로 시작하여 상위 비트를 제거하는 모든 것을 포착하고 "PNG"가 뒤 따르므로 파일에 무엇이 있는지 쉽게 알 수 있습니다. CR LF는 다양한 ASCII 라인 변환기를 포착하고 0x1a로 이전 MS-DOS 프로그램을 포착합니다. 특수 파일 끝 마커로 Ctrl-Z를 사용한 다음, 고독한 LF를 사용했습니다. 파일의 처음 몇 바이트를 보면 파일에 수행 된 작업을 정확히 알 수 있습니다.
... 즉, repair()
함수가 "손상된"입력과 "순수한"입력을 모두 받아 들일 수 있고 어떤 작업이 필요한지 안정적으로 결정할 수 있습니다.
편집 : 추가 참고 사항 : 장치 측 바이너리가 tty를 사용하여 변환을 방지하도록 tty를 구성 할 수 있습니다 cfmakeraw()
. ADB 셸 연결을 통해 라이브 화면 캡처에서 원시 비디오를 보낼 수있는 Android 5.0 prepareRawOutput()
의 screenrecord 명령에 있는 함수를 참조하세요 .
가장 좋은 해결책은 @AjeetKhadke가 제안한 adb exec-out
명령 을 사용하는 것 입니다.
adb shell
와 adb exec-out
출력 의 차이점을 설명하겠습니다 .
~$ adb shell "echo -n '\x0a'" | xxd -g1
00000000: 0d 0a
~$ adb exec-out "echo -n '\x0a'" | xxd -g1
00000000: 0a
Windows에서도 작동 합니다 (데모를 위해 GNUWin32 Hextoolshexdump
에서 사용 하고 있습니다).
C:\>adb shell "echo -n '\x0a'" | hexdump
00000000: 0D 0A
C:\>adb exec-out "echo -n '\x0a'" | hexdump
00000000: 0A
단점은 adb exec-out
명령 을 사용하여 이익을 얻으 려면 장치와 호스트 PC 모두 adb shell
V2 프로토콜 을 지원해야한다는 것 입니다.
PC 쪽을 돌보는 것은 다소 사소한 일입니다. platform-tools
패키지 ( adb
바이너리 포함 )를 최신 버전으로 업데이트하기 만하면됩니다 . adbd
기기 의 데몬 버전은 Android 버전과 연결되어 있습니다. adb shell
V2 프로토콜이 함께 완벽한 안드로이드 5.0에 도입 된 adb
정비 (에서 예정 c
에 C++
코드). 그러나 일부 회귀 (버그)가있어서 adb exec-out
Android 5.x의 유용성은 여전히 제한적이었습니다. 마지막으로 Android 4.x 및 이전 장치는 지원되지 않습니다. 다행히도 여전히 개발에 사용되는 구형 장치의 점유율이 빠르게 감소하고 있습니다.
16 진 덤프를 더 깊이 파고 들면 문자 0x0A가 방출 될 때마다 쉘이 0x0D 0x0A를 방출한다는 것이 분명해졌습니다. 다음 코드로 스트림을 복구했으며 이제 바이너리 데이터가 정확합니다. 이제 질문은 왜 adb shell이이 작업을 수행하는지입니다. 그러나 어쨌든 이것은 문제를 해결합니다.
static byte[] repair(byte[] encoded) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i=0; i<encoded.length; i++) {
if (encoded.length > i+1 && encoded[i] == 0x0d && encoded[i+1] == 0x0a) {
baos.write(0x0a);
i++;
} else {
baos.write(encoded[i]);
}
}
try {
baos.close();
} catch (IOException ioe) {
}
return baos.toByteArray();
}
편집 : 왜 이것을하고 있는지 나에게 밝혔습니다. 구식 DOS처럼 LF를 CR / LF로 변환합니다. 그것을 끄는 설정이 있는지 궁금합니다.
예, Unix / Linux / Mac OS X에서는 앞에 "stty -onlcr;"을 추가하여 adb 쉘의 바이너리 출력을 수신 할 수 있습니다. 당신의 명령에 ( 아니요 ~~ 루팅 안드로이드 필요).
1.Download "stty" executable file.
http://www.busybox.net/downloads/binaries/latest/
For old android, use busybox-armv5l, Others use busybox-armv7l.
rename file to "stty"
2.Uploda file "stty" to android and set proper permission.
adb push somelocaldir/stty /data/local/tmp/
adb shell chmod 777 /data/local/tmp/stty
3.Prepend "stty -onlcr;" to your command like this;
adb shell /data/local/tmp/stty -onlcr\; screencap -p > somelocaldir/output.png
or:
adb shell "/data/local/tmp/stty -onlcr; screencap -p" > somelocaldir/output.png
or (Only for Windows):
adb shell /data/local/tmp/stty -onlcr; screencap -p > somelocaldir/output.png
Done!
But for Windows OS, by default, LF from android will be converted to CR CR LF.
Even you did above step, you still get CR LF.
This "seems" because local adb.exe use fwrite which cause CR be prepended.
I have no way about this except convert CR LF to LF manually on Windows OS.
Another way:
adb shell "busybox stty raw; screencap -p "> foo3.png
BUT, as @osexp2003 said, that does not work for Windows OS.
Here is solution that works everywhere (Linux and Windows included).
You will need netcat
utility, often named nc
.
If both nc
and busybox nc
fail on your device, you need fresh busybox
. You can either use busybox installer from Play Market (root required), or use solution by osexp2003 (download busybox from official site, put it into /data/local/tmp/
on device and add execute permission).
The idea is to use netcat
as a primitive HTTP server.
Well, not even a proper server in fact. It will just send its input as response to any TCP connection (be it HTTP request from browser, telnet connection or just netcat
) and terminate.
Run command you want to get output from like this:
adb shell 'screencap -p | busybox nc -p 8080 -l >/dev/null'
In the above example, screencap -p
takes a screenshot (PNG image) and pipes it to netcat
.
-l
tells netcat
to act as a server (listen for connection), and -p 8080
tells it to use TCP port 8080. Omiting >/dev/null
will simply print e.g. incoming HTTP GET request to your terminal.
The above example will wait for someone to connect, send screenshot and only then terminate.
Of course you can run it without adb shell
, e.g. from terminal emulator on your device.
After running your command as above, you can download its output from your phone, by opening http://ip.of.your.phone:8080
in browser or by any other means, for example using netcat
:
busybox nc ip.of.your.phone:8080 >screenshot.png
If you want to use USB cable for download, you need to forward connection using ADB like this:
adb forward tcp:7080 tcp:8080
After that you can use localhost:7080
instead of ip.of.your.phone:8080
.
You can remove this forwarding with following command:
adb forward --remove tcp:7080
try this guys:
adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png
It is also possible to use base64 for this, so just encode it using:
base64 foo3.png>foo3.png.base64
and then on windows using some base64 utility or maybe notepad++ to decrypt the file.
Or in linux / cygwin:
base64 -d foo3.png.base64>foo3.png
You can also use the standard dos2unix
command if its available.
(apt-get install dos2unix
if you're on Debian/Ubuntu. There are probably builds for Windows, OS X, etc. out there somewhere if you google).
dos2unix
converts CRLF to LF the same way as Eric Lange's repair()
function.
adb shell screencap -p | dos2unix -f > screenshot.png
or, fix a corrupted file (in-place) :
dos2unix -f screenshot.png
You need the -f
to force it to process binary files.
I put the method to use python get image bytes using adb here, maybe this will be helpful to someone who encountered this problem. The code is as following:
pipe = subprocess.Popen("adb shell screencap -p",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, shell=True)
image_bytes = pipe.stdout.read().replace(b'\r\n', b'\n')
gray_image = cv2.imdecode(np.fromstring(image_bytes, np.uint8), cv2.IMREAD_GRAYSCALE)
nc
was the only way it worked for me. Used:
adb forward tcp:7080 tcp:8080 &&\
adb shell 'tar -zcvf - /data/media | nc -p 8080 -l 1>/dev/null' &\
sleep 1;\
nc localhost 7080 > media.tar.gz &&\
adb forward --remove tcp:7080
as root to create a hopefully proper backup for /data/media
This is the best way using Shell in OS
adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png
My bash script (default is exec-out as it works well on both devices):
https://gist.github.com/mj41/14767642e02dda7ce32ed26ce012fe12
This command worked for me on Windows OS:
adb exec-out screencap -p > test.png && dos2unix.exe -f test.png
But you want to use this: https://sourceforge.net/projects/dos2unix/
참고URL : https://stackoverflow.com/questions/13578416/read-binary-stdout-data-from-adb-shell
'IT박스' 카테고리의 다른 글
특정 폴더에서 모든 파일을 삭제하는 방법은 무엇입니까? (0) | 2020.12.10 |
---|---|
Twitter 부트 스트랩 : 진행률 표시 줄의 가운데 텍스트 (0) | 2020.12.10 |
SQL Server에서 트랜잭션을 롤백하거나 커밋하는 방법 (0) | 2020.12.10 |
파이썬에서 셀레늄 웹 드라이버로 텍스트를 얻는 방법 (0) | 2020.12.10 |
보안 문자열을 일반 텍스트로 변환 (0) | 2020.12.10 |