간단히 말해서 Bash 스크립트의 문자열이 유효한 IP 주소를 나타내는지 확인하고 싶습니다. 나는 다른 많은 사람들처럼 정규식을 사용하여 이 작업을 수행하려고 시도하는 함정에 빠졌다고 생각합니다. 이것은 IPv4에는 충분했지만 IPv6은 더 복잡하고(제로 압축을 지원하기 때문에) 복잡하고 특히 읽기 어려운 솔루션입니다. .
하지만 Unix와 Linux는 IP 주소를 명확하게 이해하므로 bash에서 IP 주소를 확인하는 더 좋은 방법이 있는지 궁금합니다. 이 작업을 수행하는 데 사용할 수 있는 상당히 일반적인 도구를 사용하는 것이 좋습니다.
filter_var
실제로 PHP 함수를 사용하는 현재 솔루션을 대체하고 싶기 때문에 다른 언어(예: Python)를 사용하지 않고 싶습니다 . 작동하지만 정규식과 마찬가지로 하나에서는 사용하지 않으려는 두 번째 언어를 소개합니다.
0.0.0.0-255.255.255.255
마지막으로, IP 주소 범위(예 : 등) 도 처리하는 솔루션이 있다면 0.0.0.0/16
이상적이겠지만 , 이를 직접 처리할 수는 있습니다.
답변1
ip 명령을 사용하는 것은 어떻습니까?
ip route get <ip-address>
유효하지 않은 경우 반환 값은 1입니다.
(2022/9/17) @MaXi32 님의 댓글에 답변을 드리기 위해 인터넷 연결 없이 제 리눅스 노트북에서 빠르게 확인해 봤습니다. 네트워크가 닫히면 ip 명령은 잘못된 IP에 대해 1을 반환하고 유효한 IP에 대해 2를 반환합니다.
유효한 IP의 경우:
$ ip route get 192.168.0.255 ; echo $?
RTNETLINK answers: Network is unreachable
2
$ ip route get fd00::192.168.0.255 ; echo $?
RTNETLINK answers: Network is unreachable
2
유효하지 않은 IP의 경우:
$ ip route get 192.168.0.256 ; echo $?
Error: any valid prefix is expected rather than "192.168.0.256".
1
$ ip route get fd00::192.168.0.256 ; echo $?
Error: any valid prefix is expected rather than "fd00::192.168.0.256".
1
IP 명령 버전:
$ ip -V
ip utility, iproute2-5.9.0, libbpf 0.3.0
(2022/9/17#2) inet_pton을 사용하여 작은 프로그램을 작성할 수 있습니다. 나는 이것이 더 낫다고 생각한다. 다음 코드는 예제에서 가져온 것입니다.inet_pton 맨페이지IP를 텍스트에서 바이너리로 변환하려고 시도하며, IP가 유효하지 않으면 오류가 발생합니다.
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
unsigned char buf[sizeof(struct in6_addr)];
int domain, s;
char str[INET6_ADDRSTRLEN];
if (argc != 3) {
fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
exit(EXIT_FAILURE);
}
domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
(strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
s = inet_pton(domain, argv[2], buf);
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
if (inet_ntop(domain, buf, str, INET6_ADDRSTRLEN) == NULL) {
perror("inet_ntop");
exit(EXIT_FAILURE);
}
printf("%s\n", str);
exit(EXIT_SUCCESS);
}
답변2
bash
관련 시스템 호출에 대한 직접적인 액세스가 부족할 수 있으므로 inet_pton(3)
이와 유사한 작업을 수행하는 호출이 필요할 수 있습니다 sipcalc
(다양한 UNIX의 포트 또는 패키지 트리에 있어야 함). 더 높은 수준의 언어도 호출을 받을 수 있지만 inet_pton(3)
세부 사항은 언어에 따라 다릅니다.NetAddr::IP
Perl의 서브넷 관련 코드.
답변3
@ktaka의 답변에 따르면 ip route get
스크립트가 네트워크 연결에 크게 의존하지 않는 한 IP 주소를 확인하는 데 사용하지 않는 것이 좋습니다. 그 이유는 시스템의 인터넷 연결이 양호하지 않거나 인터넷 연결이 완전히 끊어진 경우 ip route get
IP가 올바르게 정의된 경우에도 스크립트를 사용할 때 항상 오류 코드(0 이외의)를 반환하기 때문입니다.
해결책:
@Rolf Rander가 제공한 수동 링크를 찾아봤는데 왜 ipcalc
Debian 11의 바이너리에 해당 옵션이 없고 -c
이전 ipcalc
바이너리도 이를 지원하지 않는지 혼란스러워서 ipv6
매뉴얼에서 이 키워드를 사용하여 Google을 검색했습니다. 작성자의 사용자 이름 페이지에서 가져오며 dcantrell ipcalc
공식 링크는 여기에서 가져옵니다.
https://gitlab.com/ipcalc/ipcalc
위의 주소는 ipcalc
IPv4와 IPv6를 모두 공식적으로 지원하는 IP 주소입니다. 설치하려면 meson이 포함된 최신 빌드를 사용하는 것이 좋습니다(그러나 meson을 사용하고 싶지 않은 경우 이전 make 빌드도 제공합니다).
그래서 제가 설정한 ipcalc
방법은 다음과 같습니다 Debian 11
.
기존 ipcalc 제거(기존 버전이 불량함)
apt-get -y remove ipcalc
rm -rf "/usr/bin/ipcalc"
이제 공식 저장소에서 ipcalc를 설치하십시오.
apt -y install meson
git clone https://gitlab.com/ipcalc/ipcalc.git
cd ipcalc
meson setup build --buildtype=release
ninja -C build
cp build/ipcalc /usr/bin
apt -y remove meson
ipcalc --version
1.0.1
이제 이것을 사용하여 ipcalc
IPv4 및 IPv6를 확인할 수 있습니다.
#!/bin/bash
IP="1.1.1.1"
if ipcalc -s -c $IP; then
echo "valid IPv4 or IPv6"
else
echo "Invalid IPv4 or Ipv6"
fi
-s
오류 메시지를 무시 -c
하고 출력하지 않고 확인
특정 IPv4를 확인하려면 Check IPv6를 사용하거나 -4
사용하세요 -6
. 예:
#!/bin/bash
# IP is a valid IPv6
IP="::1"
# But we want to check only IPv4
if ipcalc -s -4 -c $IP; then
echo "valid IPv4"
else
echo "Invalid IPv4"
fi
산출:
Invalid IPv4
저는 오래 전부터 Android를 사용해 왔으며 sipcalc
IPv4와 IPv6 검사를 모두 수행하지만 대부분의 출력이 간단하고 다른 목적을 위한 json 출력이 있기 때문에 Android를 선호합니다.ipv6calc
ipcalc
편집하다
(2022년 10월 23일):
@ktaka의 최신 의견을 바탕으로 한 주요 요점은 ip route get
인터넷 연결 없이 사용할 때 다음과 같다는 것입니다.
$ ip route get 192.168.0.255 ; echo $?
RTNETLINK answers: Network is unreachable
2
시스템이 방화벽 뒤에 있거나 연결 상태가 좋지 않으면 유효한 IP가 반환되지 않습니다. IP는 유효하며 네트워크에 연결할 수 없다는 등 불필요한 정보를 알리는 대신 성공 코드 0을 반환해야 합니다.
답변4
이것은 ipv4 문제를 해결할 수 있습니다
# check IPv4 syntax
if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo 'Valid IP'
else
echo "Invalid IP: $ip" >&2
exit 1
fi
저는 제가 가져온 스크립트에 ipv6을 구현하는 중이며, 완료되면 이 게시물을 업데이트하겠습니다.